Merge pull request #343 from authorizerdev/fix/session-storage
fix: session storage
This commit is contained in:
commit
1ebba7f2b7
|
@ -21,6 +21,7 @@ require (
|
||||||
github.com/joho/godotenv v1.3.0
|
github.com/joho/godotenv v1.3.0
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
|
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
|
||||||
|
github.com/redis/go-redis/v9 v9.0.3 // indirect
|
||||||
github.com/robertkrimen/otto v0.0.0-20211024170158-b87d35c0b86f
|
github.com/robertkrimen/otto v0.0.0-20211024170158-b87d35c0b86f
|
||||||
github.com/sirupsen/logrus v1.8.1
|
github.com/sirupsen/logrus v1.8.1
|
||||||
github.com/stretchr/testify v1.8.0
|
github.com/stretchr/testify v1.8.0
|
||||||
|
|
|
@ -58,11 +58,15 @@ github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYE
|
||||||
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
|
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
|
||||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
|
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
|
||||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||||
|
github.com/bsm/ginkgo/v2 v2.7.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w=
|
||||||
|
github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
||||||
github.com/cenkalti/backoff/v4 v4.1.2 h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuDPIFo=
|
github.com/cenkalti/backoff/v4 v4.1.2 h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuDPIFo=
|
||||||
github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||||
|
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
|
@ -295,6 +299,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/redis/go-redis/v9 v9.0.3 h1:+7mmR26M0IvyLxGZUHxu4GiBkJkVDid0Un+j4ScYu4k=
|
||||||
|
github.com/redis/go-redis/v9 v9.0.3/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
|
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
github.com/robertkrimen/otto v0.0.0-20211024170158-b87d35c0b86f h1:a7clxaGmmqtdNTXyvrp/lVO/Gnkzlhc/+dLs5v965GM=
|
github.com/robertkrimen/otto v0.0.0-20211024170158-b87d35c0b86f h1:a7clxaGmmqtdNTXyvrp/lVO/Gnkzlhc/+dLs5v965GM=
|
||||||
|
|
|
@ -194,7 +194,7 @@ func AuthorizeHandler() gin.HandlerFunc {
|
||||||
// rollover the session for security
|
// rollover the session for security
|
||||||
go memorystore.Provider.DeleteUserSession(sessionKey, claims.Nonce)
|
go memorystore.Provider.DeleteUserSession(sessionKey, claims.Nonce)
|
||||||
if responseType == constants.ResponseTypeCode {
|
if responseType == constants.ResponseTypeCode {
|
||||||
newSessionTokenData, newSessionToken, err := token.CreateSessionToken(user, nonce, claims.Roles, scope, claims.LoginMethod)
|
newSessionTokenData, newSessionToken, newSessionExpiresAt, err := token.CreateSessionToken(user, nonce, claims.Roles, scope, claims.LoginMethod)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("CreateSessionToken failed: ", err)
|
log.Debug("CreateSessionToken failed: ", err)
|
||||||
handleResponse(gc, responseMode, loginURL, redirectURI, loginError, http.StatusOK)
|
handleResponse(gc, responseMode, loginURL, redirectURI, loginError, http.StatusOK)
|
||||||
|
@ -215,7 +215,7 @@ func AuthorizeHandler() gin.HandlerFunc {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+newSessionTokenData.Nonce, newSessionToken); err != nil {
|
if err := memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+newSessionTokenData.Nonce, newSessionToken, newSessionExpiresAt); err != nil {
|
||||||
log.Debug("SetUserSession failed: ", err)
|
log.Debug("SetUserSession failed: ", err)
|
||||||
handleResponse(gc, responseMode, loginURL, redirectURI, loginError, http.StatusOK)
|
handleResponse(gc, responseMode, loginURL, redirectURI, loginError, http.StatusOK)
|
||||||
return
|
return
|
||||||
|
@ -271,13 +271,13 @@ func AuthorizeHandler() gin.HandlerFunc {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+nonce, authToken.FingerPrintHash); err != nil {
|
if err := memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+nonce, authToken.FingerPrintHash, authToken.SessionTokenExpiresAt); err != nil {
|
||||||
log.Debug("SetUserSession failed: ", err)
|
log.Debug("SetUserSession failed: ", err)
|
||||||
handleResponse(gc, responseMode, loginURL, redirectURI, loginError, http.StatusOK)
|
handleResponse(gc, responseMode, loginURL, redirectURI, loginError, http.StatusOK)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+nonce, authToken.AccessToken.Token); err != nil {
|
if err := memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+nonce, authToken.AccessToken.Token, authToken.AccessToken.ExpiresAt); err != nil {
|
||||||
log.Debug("SetUserSession failed: ", err)
|
log.Debug("SetUserSession failed: ", err)
|
||||||
handleResponse(gc, responseMode, loginURL, redirectURI, loginError, http.StatusOK)
|
handleResponse(gc, responseMode, loginURL, redirectURI, loginError, http.StatusOK)
|
||||||
return
|
return
|
||||||
|
@ -305,7 +305,7 @@ func AuthorizeHandler() gin.HandlerFunc {
|
||||||
if authToken.RefreshToken != nil {
|
if authToken.RefreshToken != nil {
|
||||||
res["refresh_token"] = authToken.RefreshToken.Token
|
res["refresh_token"] = authToken.RefreshToken.Token
|
||||||
params += "&refresh_token=" + authToken.RefreshToken.Token
|
params += "&refresh_token=" + authToken.RefreshToken.Token
|
||||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token)
|
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token, authToken.RefreshToken.ExpiresAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
if responseMode == constants.ResponseModeQuery {
|
if responseMode == constants.ResponseModeQuery {
|
||||||
|
|
|
@ -47,7 +47,14 @@ func LogoutHandler() gin.HandlerFunc {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
memorystore.Provider.DeleteUserSession(sessionData.Subject, sessionData.Nonce)
|
userID := sessionData.Subject
|
||||||
|
loginMethod := sessionData.LoginMethod
|
||||||
|
sessionToken := userID
|
||||||
|
if loginMethod != "" {
|
||||||
|
sessionToken = loginMethod + ":" + userID
|
||||||
|
}
|
||||||
|
|
||||||
|
memorystore.Provider.DeleteUserSession(sessionToken, sessionData.Nonce)
|
||||||
cookie.DeleteSession(gc)
|
cookie.DeleteSession(gc)
|
||||||
|
|
||||||
if redirectURL != "" {
|
if redirectURL != "" {
|
||||||
|
|
|
@ -249,12 +249,12 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
||||||
|
|
||||||
sessionKey := provider + ":" + user.ID
|
sessionKey := provider + ":" + user.ID
|
||||||
cookie.SetSession(ctx, authToken.FingerPrintHash)
|
cookie.SetSession(ctx, authToken.FingerPrintHash)
|
||||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash)
|
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash, authToken.SessionTokenExpiresAt)
|
||||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token)
|
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token, authToken.AccessToken.ExpiresAt)
|
||||||
|
|
||||||
if authToken.RefreshToken != nil {
|
if authToken.RefreshToken != nil {
|
||||||
params += `&refresh_token=` + authToken.RefreshToken.Token
|
params += `&refresh_token=` + authToken.RefreshToken.Token
|
||||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token)
|
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token, authToken.RefreshToken.ExpiresAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
|
|
@ -247,8 +247,8 @@ func TokenHandler() gin.HandlerFunc {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash)
|
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash, authToken.SessionTokenExpiresAt)
|
||||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token)
|
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token, authToken.AccessToken.ExpiresAt)
|
||||||
cookie.SetSession(gc, authToken.FingerPrintHash)
|
cookie.SetSession(gc, authToken.FingerPrintHash)
|
||||||
|
|
||||||
expiresIn := authToken.AccessToken.ExpiresAt - time.Now().Unix()
|
expiresIn := authToken.AccessToken.ExpiresAt - time.Now().Unix()
|
||||||
|
@ -266,7 +266,7 @@ func TokenHandler() gin.HandlerFunc {
|
||||||
|
|
||||||
if authToken.RefreshToken != nil {
|
if authToken.RefreshToken != nil {
|
||||||
res["refresh_token"] = authToken.RefreshToken.Token
|
res["refresh_token"] = authToken.RefreshToken.Token
|
||||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token)
|
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token, authToken.RefreshToken.ExpiresAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
gc.JSON(http.StatusOK, res)
|
gc.JSON(http.StatusOK, res)
|
||||||
|
|
|
@ -154,12 +154,12 @@ func VerifyEmailHandler() gin.HandlerFunc {
|
||||||
|
|
||||||
sessionKey := loginMethod + ":" + user.ID
|
sessionKey := loginMethod + ":" + user.ID
|
||||||
cookie.SetSession(c, authToken.FingerPrintHash)
|
cookie.SetSession(c, authToken.FingerPrintHash)
|
||||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash)
|
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash, authToken.SessionTokenExpiresAt)
|
||||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token)
|
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token, authToken.AccessToken.ExpiresAt)
|
||||||
|
|
||||||
if authToken.RefreshToken != nil {
|
if authToken.RefreshToken != nil {
|
||||||
params = params + `&refresh_token=` + authToken.RefreshToken.Token
|
params = params + `&refresh_token=` + authToken.RefreshToken.Token
|
||||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token)
|
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token, authToken.RefreshToken.ExpiresAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
if redirectURL == "" {
|
if redirectURL == "" {
|
||||||
|
|
14
server/memorystore/providers/inmemory/provider_test.go
Normal file
14
server/memorystore/providers/inmemory/provider_test.go
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
package inmemory
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/memorystore/providers"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestInMemoryProvider(t *testing.T) {
|
||||||
|
p, err := NewInMemoryProvider()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
providers.ProviderTests(t, p)
|
||||||
|
}
|
|
@ -8,45 +8,31 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetUserSession sets the user session for given user identifier in form recipe:user_id
|
// SetUserSession sets the user session for given user identifier in form recipe:user_id
|
||||||
func (c *provider) SetUserSession(userId, key, token string) error {
|
func (c *provider) SetUserSession(userId, key, token string, expiration int64) error {
|
||||||
c.sessionStore.Set(userId, key, token)
|
c.sessionStore.Set(userId, key, token, expiration)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAllUserSessions returns all the user sessions token from the in-memory store.
|
|
||||||
func (c *provider) GetAllUserSessions(userId string) (map[string]string, error) {
|
|
||||||
data := c.sessionStore.GetAll(userId)
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUserSession returns value for given session token
|
// GetUserSession returns value for given session token
|
||||||
func (c *provider) GetUserSession(userId, sessionToken string) (string, error) {
|
func (c *provider) GetUserSession(userId, sessionToken string) (string, error) {
|
||||||
return c.sessionStore.Get(userId, sessionToken), nil
|
val := c.sessionStore.Get(userId, sessionToken)
|
||||||
|
if val == "" {
|
||||||
|
return "", fmt.Errorf("Not found")
|
||||||
|
}
|
||||||
|
return val, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteAllUserSessions deletes all the user sessions from in-memory store.
|
// DeleteAllUserSessions deletes all the user sessions from in-memory store.
|
||||||
func (c *provider) DeleteAllUserSessions(userId string) error {
|
func (c *provider) DeleteAllUserSessions(userId string) error {
|
||||||
namespaces := []string{
|
c.sessionStore.RemoveAll(userId)
|
||||||
constants.AuthRecipeMethodBasicAuth,
|
|
||||||
constants.AuthRecipeMethodMagicLinkLogin,
|
|
||||||
constants.AuthRecipeMethodApple,
|
|
||||||
constants.AuthRecipeMethodFacebook,
|
|
||||||
constants.AuthRecipeMethodGithub,
|
|
||||||
constants.AuthRecipeMethodGoogle,
|
|
||||||
constants.AuthRecipeMethodLinkedIn,
|
|
||||||
constants.AuthRecipeMethodTwitter,
|
|
||||||
constants.AuthRecipeMethodMicrosoft,
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, namespace := range namespaces {
|
|
||||||
c.sessionStore.RemoveAll(namespace + ":" + userId)
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteUserSession deletes the user session from the in-memory store.
|
// DeleteUserSession deletes the user session from the in-memory store.
|
||||||
func (c *provider) DeleteUserSession(userId, sessionToken string) error {
|
func (c *provider) DeleteUserSession(userId, sessionToken string) error {
|
||||||
c.sessionStore.Remove(userId, sessionToken)
|
c.sessionStore.Remove(userId, constants.TokenTypeSessionToken+"_"+sessionToken)
|
||||||
|
c.sessionStore.Remove(userId, constants.TokenTypeAccessToken+"_"+sessionToken)
|
||||||
|
c.sessionStore.Remove(userId, constants.TokenTypeRefreshToken+"_"+sessionToken)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,11 +31,15 @@ func (e *EnvStore) UpdateStore(store map[string]interface{}) {
|
||||||
|
|
||||||
// GetStore returns the env store
|
// GetStore returns the env store
|
||||||
func (e *EnvStore) GetStore() map[string]interface{} {
|
func (e *EnvStore) GetStore() map[string]interface{} {
|
||||||
|
e.mutex.Lock()
|
||||||
|
defer e.mutex.Unlock()
|
||||||
return e.store
|
return e.store
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get returns the value of the key in evn store
|
// Get returns the value of the key in evn store
|
||||||
func (e *EnvStore) Get(key string) interface{} {
|
func (e *EnvStore) Get(key string) interface{} {
|
||||||
|
e.mutex.Lock()
|
||||||
|
defer e.mutex.Unlock()
|
||||||
return e.store[key]
|
return e.store[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,73 +1,140 @@
|
||||||
package stores
|
package stores
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Maximum entries to keep in session storage
|
||||||
|
maxCacheSize = 1000
|
||||||
|
// Cache clear interval
|
||||||
|
clearInterval = 10 * time.Minute
|
||||||
|
)
|
||||||
|
|
||||||
|
// SessionEntry is the struct for entry stored in store
|
||||||
|
type SessionEntry struct {
|
||||||
|
Value string
|
||||||
|
ExpiresAt int64
|
||||||
|
}
|
||||||
|
|
||||||
// SessionStore struct to store the env variables
|
// SessionStore struct to store the env variables
|
||||||
type SessionStore struct {
|
type SessionStore struct {
|
||||||
mutex sync.Mutex
|
wg sync.WaitGroup
|
||||||
store map[string]map[string]string
|
mutex sync.RWMutex
|
||||||
|
store map[string]*SessionEntry
|
||||||
|
// stores expireTime: key to remove data when cache is full
|
||||||
|
// map is sorted by key so older most entry can be deleted first
|
||||||
|
keyIndex map[int64]string
|
||||||
|
stop chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSessionStore create a new session store
|
// NewSessionStore create a new session store
|
||||||
func NewSessionStore() *SessionStore {
|
func NewSessionStore() *SessionStore {
|
||||||
return &SessionStore{
|
store := &SessionStore{
|
||||||
mutex: sync.Mutex{},
|
mutex: sync.RWMutex{},
|
||||||
store: make(map[string]map[string]string),
|
store: make(map[string]*SessionEntry),
|
||||||
|
keyIndex: make(map[int64]string),
|
||||||
|
stop: make(chan struct{}),
|
||||||
|
}
|
||||||
|
store.wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer store.wg.Done()
|
||||||
|
store.clean()
|
||||||
|
}()
|
||||||
|
return store
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SessionStore) clean() {
|
||||||
|
t := time.NewTicker(clearInterval)
|
||||||
|
defer t.Stop()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-s.stop:
|
||||||
|
return
|
||||||
|
case <-t.C:
|
||||||
|
s.mutex.Lock()
|
||||||
|
currentTime := time.Now().Unix()
|
||||||
|
for k, v := range s.store {
|
||||||
|
if v.ExpiresAt < currentTime {
|
||||||
|
delete(s.store, k)
|
||||||
|
delete(s.keyIndex, v.ExpiresAt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.mutex.Unlock()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get returns the value of the key in state store
|
// Get returns the value of the key in state store
|
||||||
func (s *SessionStore) Get(key, subKey string) string {
|
func (s *SessionStore) Get(key, subKey string) string {
|
||||||
return s.store[key][subKey]
|
s.mutex.RLock()
|
||||||
|
defer s.mutex.RUnlock()
|
||||||
|
currentTime := time.Now().Unix()
|
||||||
|
k := fmt.Sprintf("%s:%s", key, subKey)
|
||||||
|
if v, ok := s.store[k]; ok {
|
||||||
|
if v.ExpiresAt > currentTime {
|
||||||
|
return v.Value
|
||||||
|
}
|
||||||
|
// Delete expired items
|
||||||
|
delete(s.store, k)
|
||||||
|
}
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set sets the value of the key in state store
|
// Set sets the value of the key in state store
|
||||||
func (s *SessionStore) Set(key string, subKey, value string) {
|
func (s *SessionStore) Set(key string, subKey, value string, expiration int64) {
|
||||||
s.mutex.Lock()
|
s.mutex.Lock()
|
||||||
defer s.mutex.Unlock()
|
defer s.mutex.Unlock()
|
||||||
|
k := fmt.Sprintf("%s:%s", key, subKey)
|
||||||
if _, ok := s.store[key]; !ok {
|
if _, ok := s.store[k]; !ok {
|
||||||
s.store[key] = make(map[string]string)
|
// check if there is enough space in cache
|
||||||
|
// else delete entries based on FIFO
|
||||||
|
if len(s.store) == maxCacheSize {
|
||||||
|
// remove older most entry
|
||||||
|
sortedKeys := []int64{}
|
||||||
|
for ik := range s.keyIndex {
|
||||||
|
sortedKeys = append(sortedKeys, ik)
|
||||||
}
|
}
|
||||||
s.store[key][subKey] = value
|
sort.Slice(sortedKeys, func(i, j int) bool { return sortedKeys[i] < sortedKeys[j] })
|
||||||
|
itemToRemove := sortedKeys[0]
|
||||||
|
delete(s.store, s.keyIndex[itemToRemove])
|
||||||
|
delete(s.keyIndex, itemToRemove)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.store[k] = &SessionEntry{
|
||||||
|
Value: value,
|
||||||
|
ExpiresAt: expiration,
|
||||||
|
}
|
||||||
|
s.keyIndex[expiration] = k
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveAll all values for given key
|
// RemoveAll all values for given key
|
||||||
func (s *SessionStore) RemoveAll(key string) {
|
func (s *SessionStore) RemoveAll(key string) {
|
||||||
s.mutex.Lock()
|
s.mutex.Lock()
|
||||||
defer s.mutex.Unlock()
|
defer s.mutex.Unlock()
|
||||||
|
for k := range s.store {
|
||||||
delete(s.store, key)
|
if strings.Contains(k, key) {
|
||||||
|
delete(s.store, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove value for given key and subkey
|
// Remove value for given key and subkey
|
||||||
func (s *SessionStore) Remove(key, subKey string) {
|
func (s *SessionStore) Remove(key, subKey string) {
|
||||||
s.mutex.Lock()
|
s.mutex.Lock()
|
||||||
defer s.mutex.Unlock()
|
defer s.mutex.Unlock()
|
||||||
if _, ok := s.store[key]; ok {
|
k := fmt.Sprintf("%s:%s", key, subKey)
|
||||||
delete(s.store[key], subKey)
|
delete(s.store, k)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get all the values for given key
|
|
||||||
func (s *SessionStore) GetAll(key string) map[string]string {
|
|
||||||
s.mutex.Lock()
|
|
||||||
defer s.mutex.Unlock()
|
|
||||||
|
|
||||||
if _, ok := s.store[key]; !ok {
|
|
||||||
s.store[key] = make(map[string]string)
|
|
||||||
}
|
|
||||||
return s.store[key]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveByNamespace to delete session for a given namespace example google,github
|
// RemoveByNamespace to delete session for a given namespace example google,github
|
||||||
func (s *SessionStore) RemoveByNamespace(namespace string) error {
|
func (s *SessionStore) RemoveByNamespace(namespace string) error {
|
||||||
s.mutex.Lock()
|
s.mutex.Lock()
|
||||||
defer s.mutex.Unlock()
|
defer s.mutex.Unlock()
|
||||||
|
|
||||||
for key := range s.store {
|
for key := range s.store {
|
||||||
if strings.Contains(key, namespace+":") {
|
if strings.Contains(key, namespace+":") {
|
||||||
delete(s.store, key)
|
delete(s.store, key)
|
||||||
|
|
|
@ -20,6 +20,8 @@ func NewStateStore() *StateStore {
|
||||||
|
|
||||||
// Get returns the value of the key in state store
|
// Get returns the value of the key in state store
|
||||||
func (s *StateStore) Get(key string) string {
|
func (s *StateStore) Get(key string) string {
|
||||||
|
s.mutex.Lock()
|
||||||
|
defer s.mutex.Unlock()
|
||||||
return s.store[key]
|
return s.store[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
115
server/memorystore/providers/provider_tests.go
Normal file
115
server/memorystore/providers/provider_tests.go
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
package providers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ProviderTests runs all provider tests
|
||||||
|
func ProviderTests(t *testing.T, p Provider) {
|
||||||
|
|
||||||
|
err := p.SetUserSession("auth_provider:123", "session_token_key", "test_hash123", time.Now().Add(60*time.Second).Unix())
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = p.SetUserSession("auth_provider:123", "access_token_key", "test_jwt123", time.Now().Add(60*time.Second).Unix())
|
||||||
|
assert.NoError(t, err)
|
||||||
|
// Same user multiple session
|
||||||
|
err = p.SetUserSession("auth_provider:123", "session_token_key1", "test_hash1123", time.Now().Add(60*time.Second).Unix())
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = p.SetUserSession("auth_provider:123", "access_token_key1", "test_jwt1123", time.Now().Add(60*time.Second).Unix())
|
||||||
|
assert.NoError(t, err)
|
||||||
|
// Different user session
|
||||||
|
err = p.SetUserSession("auth_provider:124", "session_token_key", "test_hash124", time.Now().Add(5*time.Second).Unix())
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = p.SetUserSession("auth_provider:124", "access_token_key", "test_jwt124", time.Now().Add(5*time.Second).Unix())
|
||||||
|
assert.NoError(t, err)
|
||||||
|
// Different provider session
|
||||||
|
err = p.SetUserSession("auth_provider1:124", "session_token_key", "test_hash124", time.Now().Add(60*time.Second).Unix())
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = p.SetUserSession("auth_provider1:124", "access_token_key", "test_jwt124", time.Now().Add(60*time.Second).Unix())
|
||||||
|
assert.NoError(t, err)
|
||||||
|
// Different provider session
|
||||||
|
err = p.SetUserSession("auth_provider1:123", "session_token_key", "test_hash1123", time.Now().Add(60*time.Second).Unix())
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = p.SetUserSession("auth_provider1:123", "access_token_key", "test_jwt1123", time.Now().Add(60*time.Second).Unix())
|
||||||
|
assert.NoError(t, err)
|
||||||
|
// Get session
|
||||||
|
key, err := p.GetUserSession("auth_provider:123", "session_token_key")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "test_hash123", key)
|
||||||
|
key, err = p.GetUserSession("auth_provider:123", "access_token_key")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "test_jwt123", key)
|
||||||
|
key, err = p.GetUserSession("auth_provider:124", "session_token_key")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "test_hash124", key)
|
||||||
|
key, err = p.GetUserSession("auth_provider:124", "access_token_key")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "test_jwt124", key)
|
||||||
|
// Expire some tokens and make sure they are empty
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
key, err = p.GetUserSession("auth_provider:124", "session_token_key")
|
||||||
|
assert.Empty(t, key)
|
||||||
|
assert.Error(t, err)
|
||||||
|
key, err = p.GetUserSession("auth_provider:124", "access_token_key")
|
||||||
|
assert.Empty(t, key)
|
||||||
|
assert.Error(t, err)
|
||||||
|
// Delete user session
|
||||||
|
err = p.DeleteUserSession("auth_provider:123", "key")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = p.DeleteUserSession("auth_provider:123", "key")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
key, err = p.GetUserSession("auth_provider:123", "key")
|
||||||
|
assert.Empty(t, key)
|
||||||
|
assert.Error(t, err)
|
||||||
|
key, err = p.GetUserSession("auth_provider:123", "access_token_key")
|
||||||
|
assert.Empty(t, key)
|
||||||
|
assert.Error(t, err)
|
||||||
|
// Delete all user session
|
||||||
|
err = p.DeleteAllUserSessions("123")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = p.DeleteAllUserSessions("123")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
key, err = p.GetUserSession("auth_provider:123", "session_token_key1")
|
||||||
|
assert.Empty(t, key)
|
||||||
|
assert.Error(t, err)
|
||||||
|
key, err = p.GetUserSession("auth_provider:123", "access_token_key1")
|
||||||
|
assert.Empty(t, key)
|
||||||
|
assert.Error(t, err)
|
||||||
|
key, err = p.GetUserSession("auth_provider1:123", "session_token_key")
|
||||||
|
assert.Empty(t, key)
|
||||||
|
assert.Error(t, err)
|
||||||
|
key, err = p.GetUserSession("auth_provider1:123", "access_token_key")
|
||||||
|
assert.Empty(t, key)
|
||||||
|
assert.Error(t, err)
|
||||||
|
// Delete namespace
|
||||||
|
err = p.DeleteSessionForNamespace("auth_provider")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = p.DeleteSessionForNamespace("auth_provider1")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
key, err = p.GetUserSession("auth_provider:123", "session_token_key1")
|
||||||
|
assert.Empty(t, key)
|
||||||
|
assert.Error(t, err)
|
||||||
|
key, err = p.GetUserSession("auth_provider:123", "access_token_key1")
|
||||||
|
assert.Empty(t, key)
|
||||||
|
assert.Error(t, err)
|
||||||
|
key, err = p.GetUserSession("auth_provider1:123", "session_token_key")
|
||||||
|
assert.Empty(t, key)
|
||||||
|
assert.Error(t, err)
|
||||||
|
key, err = p.GetUserSession("auth_provider1:123", "access_token_key")
|
||||||
|
assert.Empty(t, key)
|
||||||
|
assert.Error(t, err)
|
||||||
|
key, err = p.GetUserSession("auth_provider:124", "session_token_key1")
|
||||||
|
assert.Empty(t, key)
|
||||||
|
assert.Error(t, err)
|
||||||
|
key, err = p.GetUserSession("auth_provider:124", "access_token_key1")
|
||||||
|
assert.Empty(t, key)
|
||||||
|
assert.Error(t, err)
|
||||||
|
key, err = p.GetUserSession("auth_provider1:124", "session_token_key")
|
||||||
|
assert.Empty(t, key)
|
||||||
|
assert.Error(t, err)
|
||||||
|
key, err = p.GetUserSession("auth_provider1:124", "access_token_key")
|
||||||
|
assert.Empty(t, key)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
|
@ -3,9 +3,7 @@ package providers
|
||||||
// Provider defines current memory store provider
|
// Provider defines current memory store provider
|
||||||
type Provider interface {
|
type Provider interface {
|
||||||
// SetUserSession sets the user session for given user identifier in form recipe:user_id
|
// SetUserSession sets the user session for given user identifier in form recipe:user_id
|
||||||
SetUserSession(userId, key, token string) error
|
SetUserSession(userId, key, token string, expiration int64) error
|
||||||
// GetAllUserSessions returns all the user sessions from the session store
|
|
||||||
GetAllUserSessions(userId string) (map[string]string, error)
|
|
||||||
// GetUserSession returns the session token for given token
|
// GetUserSession returns the session token for given token
|
||||||
GetUserSession(userId, key string) (string, error)
|
GetUserSession(userId, key string) (string, error)
|
||||||
// DeleteUserSession deletes the user session
|
// DeleteUserSession deletes the user session
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-redis/redis/v8"
|
"github.com/redis/go-redis/v9"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -17,10 +17,11 @@ type RedisClient interface {
|
||||||
HMGet(ctx context.Context, key string, fields ...string) *redis.SliceCmd
|
HMGet(ctx context.Context, key string, fields ...string) *redis.SliceCmd
|
||||||
HSet(ctx context.Context, key string, values ...interface{}) *redis.IntCmd
|
HSet(ctx context.Context, key string, values ...interface{}) *redis.IntCmd
|
||||||
HGet(ctx context.Context, key, field string) *redis.StringCmd
|
HGet(ctx context.Context, key, field string) *redis.StringCmd
|
||||||
HGetAll(ctx context.Context, key string) *redis.StringStringMapCmd
|
HGetAll(ctx context.Context, key string) *redis.MapStringStringCmd
|
||||||
Set(ctx context.Context, key string, value interface{}, expiration time.Duration) *redis.StatusCmd
|
Set(ctx context.Context, key string, value interface{}, expiration time.Duration) *redis.StatusCmd
|
||||||
Get(ctx context.Context, key string) *redis.StringCmd
|
Get(ctx context.Context, key string) *redis.StringCmd
|
||||||
Scan(ctx context.Context, cursor uint64, match string, count int64) *redis.ScanCmd
|
Scan(ctx context.Context, cursor uint64, match string, count int64) *redis.ScanCmd
|
||||||
|
Keys(ctx context.Context, pattern string) *redis.StringSliceCmd
|
||||||
}
|
}
|
||||||
|
|
||||||
type provider struct {
|
type provider struct {
|
||||||
|
@ -31,7 +32,6 @@ type provider struct {
|
||||||
// NewRedisProvider returns a new redis provider
|
// NewRedisProvider returns a new redis provider
|
||||||
func NewRedisProvider(redisURL string) (*provider, error) {
|
func NewRedisProvider(redisURL string) (*provider, error) {
|
||||||
redisURLHostPortsList := strings.Split(redisURL, ",")
|
redisURLHostPortsList := strings.Split(redisURL, ",")
|
||||||
|
|
||||||
if len(redisURLHostPortsList) > 1 {
|
if len(redisURLHostPortsList) > 1 {
|
||||||
opt, err := redis.ParseURL(redisURLHostPortsList[0])
|
opt, err := redis.ParseURL(redisURLHostPortsList[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -70,7 +70,6 @@ func NewRedisProvider(redisURL string) (*provider, error) {
|
||||||
log.Debug("error connecting to redis: ", err)
|
log.Debug("error connecting to redis: ", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &provider{
|
return &provider{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
store: rdb,
|
store: rdb,
|
||||||
|
|
15
server/memorystore/providers/redis/provider_test.go
Normal file
15
server/memorystore/providers/redis/provider_test.go
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
package redis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/memorystore/providers"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRedisProvider(t *testing.T) {
|
||||||
|
p, err := NewRedisProvider("redis://127.0.0.1:6379")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
providers.ProviderTests(t, p)
|
||||||
|
}
|
|
@ -1,7 +1,9 @@
|
||||||
package redis
|
package redis
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
@ -15,29 +17,21 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetUserSession sets the user session for given user identifier in form recipe:user_id
|
// SetUserSession sets the user session for given user identifier in form recipe:user_id
|
||||||
func (c *provider) SetUserSession(userId, key, token string) error {
|
func (c *provider) SetUserSession(userId, key, token string, expiration int64) error {
|
||||||
err := c.store.HSet(c.ctx, userId, key, token).Err()
|
currentTime := time.Now()
|
||||||
|
expireTime := time.Unix(expiration, 0)
|
||||||
|
duration := expireTime.Sub(currentTime)
|
||||||
|
err := c.store.Set(c.ctx, fmt.Sprintf("%s:%s", userId, key), token, duration).Err()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("Error saving to redis: ", err)
|
log.Debug("Error saving user session to redis: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAllUserSessions returns all the user session token from the redis store.
|
|
||||||
func (c *provider) GetAllUserSessions(userID string) (map[string]string, error) {
|
|
||||||
data, err := c.store.HGetAll(c.ctx, userID).Result()
|
|
||||||
if err != nil {
|
|
||||||
log.Debug("error getting all user sessions from redis store: ", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUserSession returns the user session from redis store.
|
// GetUserSession returns the user session from redis store.
|
||||||
func (c *provider) GetUserSession(userId, key string) (string, error) {
|
func (c *provider) GetUserSession(userId, key string) (string, error) {
|
||||||
data, err := c.store.HGet(c.ctx, userId, key).Result()
|
data, err := c.store.Get(c.ctx, fmt.Sprintf("%s:%s", userId, key)).Result()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -46,39 +40,34 @@ func (c *provider) GetUserSession(userId, key string) (string, error) {
|
||||||
|
|
||||||
// DeleteUserSession deletes the user session from redis store.
|
// DeleteUserSession deletes the user session from redis store.
|
||||||
func (c *provider) DeleteUserSession(userId, key string) error {
|
func (c *provider) DeleteUserSession(userId, key string) error {
|
||||||
if err := c.store.HDel(c.ctx, userId, constants.TokenTypeSessionToken+"_"+key).Err(); err != nil {
|
if err := c.store.Del(c.ctx, fmt.Sprintf("%s:%s", userId, constants.TokenTypeSessionToken+"_"+key)).Err(); err != nil {
|
||||||
log.Debug("Error deleting user session from redis: ", err)
|
log.Debug("Error deleting user session from redis: ", err)
|
||||||
return err
|
// continue
|
||||||
}
|
}
|
||||||
if err := c.store.HDel(c.ctx, userId, constants.TokenTypeAccessToken+"_"+key).Err(); err != nil {
|
if err := c.store.Del(c.ctx, fmt.Sprintf("%s:%s", userId, constants.TokenTypeAccessToken+"_"+key)).Err(); err != nil {
|
||||||
log.Debug("Error deleting user session from redis: ", err)
|
log.Debug("Error deleting user session from redis: ", err)
|
||||||
return err
|
// continue
|
||||||
}
|
}
|
||||||
if err := c.store.HDel(c.ctx, userId, constants.TokenTypeRefreshToken+"_"+key).Err(); err != nil {
|
if err := c.store.Del(c.ctx, fmt.Sprintf("%s:%s", userId, constants.TokenTypeRefreshToken+"_"+key)).Err(); err != nil {
|
||||||
log.Debug("Error deleting user session from redis: ", err)
|
log.Debug("Error deleting user session from redis: ", err)
|
||||||
return err
|
// continue
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteAllUserSessions deletes all the user session from redis
|
// DeleteAllUserSessions deletes all the user session from redis
|
||||||
func (c *provider) DeleteAllUserSessions(userID string) error {
|
func (c *provider) DeleteAllUserSessions(userID string) error {
|
||||||
namespaces := []string{
|
res := c.store.Keys(c.ctx, fmt.Sprintf("*%s*", userID))
|
||||||
constants.AuthRecipeMethodBasicAuth,
|
if res.Err() != nil {
|
||||||
constants.AuthRecipeMethodMagicLinkLogin,
|
log.Debug("Error getting all user sessions from redis: ", res.Err())
|
||||||
constants.AuthRecipeMethodApple,
|
return res.Err()
|
||||||
constants.AuthRecipeMethodFacebook,
|
|
||||||
constants.AuthRecipeMethodGithub,
|
|
||||||
constants.AuthRecipeMethodGoogle,
|
|
||||||
constants.AuthRecipeMethodLinkedIn,
|
|
||||||
constants.AuthRecipeMethodTwitter,
|
|
||||||
constants.AuthRecipeMethodMicrosoft,
|
|
||||||
}
|
}
|
||||||
for _, namespace := range namespaces {
|
keys := res.Val()
|
||||||
err := c.store.Del(c.ctx, namespace+":"+userID).Err()
|
for _, key := range keys {
|
||||||
|
err := c.store.Del(c.ctx, key).Err()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("Error deleting all user sessions from redis: ", err)
|
log.Debug("Error deleting all user sessions from redis: ", err)
|
||||||
return err
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -86,27 +75,19 @@ func (c *provider) DeleteAllUserSessions(userID string) error {
|
||||||
|
|
||||||
// DeleteSessionForNamespace to delete session for a given namespace example google,github
|
// DeleteSessionForNamespace to delete session for a given namespace example google,github
|
||||||
func (c *provider) DeleteSessionForNamespace(namespace string) error {
|
func (c *provider) DeleteSessionForNamespace(namespace string) error {
|
||||||
var cursor uint64
|
res := c.store.Keys(c.ctx, fmt.Sprintf("%s:*", namespace))
|
||||||
for {
|
if res.Err() != nil {
|
||||||
keys := []string{}
|
log.Debug("Error getting all user sessions from redis: ", res.Err())
|
||||||
keys, cursor, err := c.store.Scan(c.ctx, cursor, namespace+":*", 0).Result()
|
return res.Err()
|
||||||
if err != nil {
|
|
||||||
log.Debugf("Error scanning keys for %s namespace: %s", namespace, err.Error())
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
keys := res.Val()
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
err := c.store.Del(c.ctx, key).Err()
|
err := c.store.Del(c.ctx, key).Err()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("Error deleting sessions for %s namespace: %s", namespace, err.Error())
|
log.Debug("Error deleting all user sessions from redis: ", err)
|
||||||
return err
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if cursor == 0 { // no more keys
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -193,12 +193,12 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
|
||||||
|
|
||||||
cookie.SetSession(gc, authToken.FingerPrintHash)
|
cookie.SetSession(gc, authToken.FingerPrintHash)
|
||||||
sessionStoreKey := constants.AuthRecipeMethodBasicAuth + ":" + user.ID
|
sessionStoreKey := constants.AuthRecipeMethodBasicAuth + ":" + user.ID
|
||||||
memorystore.Provider.SetUserSession(sessionStoreKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash)
|
memorystore.Provider.SetUserSession(sessionStoreKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash, authToken.SessionTokenExpiresAt)
|
||||||
memorystore.Provider.SetUserSession(sessionStoreKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token)
|
memorystore.Provider.SetUserSession(sessionStoreKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token, authToken.AccessToken.ExpiresAt)
|
||||||
|
|
||||||
if authToken.RefreshToken != nil {
|
if authToken.RefreshToken != nil {
|
||||||
res.RefreshToken = &authToken.RefreshToken.Token
|
res.RefreshToken = &authToken.RefreshToken.Token
|
||||||
memorystore.Provider.SetUserSession(sessionStoreKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token)
|
memorystore.Provider.SetUserSession(sessionStoreKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token, authToken.RefreshToken.ExpiresAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
|
|
@ -195,12 +195,12 @@ func MobileLoginResolver(ctx context.Context, params model.MobileLoginInput) (*m
|
||||||
|
|
||||||
cookie.SetSession(gc, authToken.FingerPrintHash)
|
cookie.SetSession(gc, authToken.FingerPrintHash)
|
||||||
sessionStoreKey := constants.AuthRecipeMethodMobileBasicAuth + ":" + user.ID
|
sessionStoreKey := constants.AuthRecipeMethodMobileBasicAuth + ":" + user.ID
|
||||||
memorystore.Provider.SetUserSession(sessionStoreKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash)
|
memorystore.Provider.SetUserSession(sessionStoreKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash, authToken.SessionTokenExpiresAt)
|
||||||
memorystore.Provider.SetUserSession(sessionStoreKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token)
|
memorystore.Provider.SetUserSession(sessionStoreKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token, authToken.AccessToken.ExpiresAt)
|
||||||
|
|
||||||
if authToken.RefreshToken != nil {
|
if authToken.RefreshToken != nil {
|
||||||
res.RefreshToken = &authToken.RefreshToken.Token
|
res.RefreshToken = &authToken.RefreshToken.Token
|
||||||
memorystore.Provider.SetUserSession(sessionStoreKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token)
|
memorystore.Provider.SetUserSession(sessionStoreKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token, authToken.RefreshToken.ExpiresAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
|
|
@ -249,12 +249,12 @@ func MobileSignupResolver(ctx context.Context, params *model.MobileSignUpInput)
|
||||||
|
|
||||||
sessionKey := constants.AuthRecipeMethodMobileBasicAuth + ":" + user.ID
|
sessionKey := constants.AuthRecipeMethodMobileBasicAuth + ":" + user.ID
|
||||||
cookie.SetSession(gc, authToken.FingerPrintHash)
|
cookie.SetSession(gc, authToken.FingerPrintHash)
|
||||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash)
|
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash, authToken.SessionTokenExpiresAt)
|
||||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token)
|
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token, authToken.AccessToken.ExpiresAt)
|
||||||
|
|
||||||
if authToken.RefreshToken != nil {
|
if authToken.RefreshToken != nil {
|
||||||
res.RefreshToken = &authToken.RefreshToken.Token
|
res.RefreshToken = &authToken.RefreshToken.Token
|
||||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token)
|
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token, authToken.RefreshToken.ExpiresAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
|
|
@ -99,12 +99,12 @@ func SessionResolver(ctx context.Context, params *model.SessionQueryInput) (*mod
|
||||||
}
|
}
|
||||||
|
|
||||||
cookie.SetSession(gc, authToken.FingerPrintHash)
|
cookie.SetSession(gc, authToken.FingerPrintHash)
|
||||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash)
|
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash, authToken.SessionTokenExpiresAt)
|
||||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token)
|
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token, authToken.AccessToken.ExpiresAt)
|
||||||
|
|
||||||
if authToken.RefreshToken != nil {
|
if authToken.RefreshToken != nil {
|
||||||
res.RefreshToken = &authToken.RefreshToken.Token
|
res.RefreshToken = &authToken.RefreshToken.Token
|
||||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token)
|
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token, authToken.RefreshToken.ExpiresAt)
|
||||||
}
|
}
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,6 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
||||||
}
|
}
|
||||||
|
|
||||||
inputRoles := []string{}
|
inputRoles := []string{}
|
||||||
|
|
||||||
if len(params.Roles) > 0 {
|
if len(params.Roles) > 0 {
|
||||||
// check if roles exists
|
// check if roles exists
|
||||||
rolesString, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyRoles)
|
rolesString, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyRoles)
|
||||||
|
@ -293,12 +292,12 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
||||||
|
|
||||||
sessionKey := constants.AuthRecipeMethodBasicAuth + ":" + user.ID
|
sessionKey := constants.AuthRecipeMethodBasicAuth + ":" + user.ID
|
||||||
cookie.SetSession(gc, authToken.FingerPrintHash)
|
cookie.SetSession(gc, authToken.FingerPrintHash)
|
||||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash)
|
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash, authToken.SessionTokenExpiresAt)
|
||||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token)
|
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token, authToken.AccessToken.ExpiresAt)
|
||||||
|
|
||||||
if authToken.RefreshToken != nil {
|
if authToken.RefreshToken != nil {
|
||||||
res.RefreshToken = &authToken.RefreshToken.Token
|
res.RefreshToken = &authToken.RefreshToken.Token
|
||||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token)
|
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token, authToken.RefreshToken.ExpiresAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
|
|
@ -150,12 +150,12 @@ func VerifyEmailResolver(ctx context.Context, params model.VerifyEmailInput) (*m
|
||||||
|
|
||||||
sessionKey := loginMethod + ":" + user.ID
|
sessionKey := loginMethod + ":" + user.ID
|
||||||
cookie.SetSession(gc, authToken.FingerPrintHash)
|
cookie.SetSession(gc, authToken.FingerPrintHash)
|
||||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash)
|
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash, authToken.SessionTokenExpiresAt)
|
||||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token)
|
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token, authToken.AccessToken.ExpiresAt)
|
||||||
|
|
||||||
if authToken.RefreshToken != nil {
|
if authToken.RefreshToken != nil {
|
||||||
res.RefreshToken = &authToken.RefreshToken.Token
|
res.RefreshToken = &authToken.RefreshToken.Token
|
||||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token)
|
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token, authToken.RefreshToken.ExpiresAt)
|
||||||
}
|
}
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,12 +123,12 @@ func VerifyOtpResolver(ctx context.Context, params model.VerifyOTPRequest) (*mod
|
||||||
|
|
||||||
sessionKey := loginMethod + ":" + user.ID
|
sessionKey := loginMethod + ":" + user.ID
|
||||||
cookie.SetSession(gc, authToken.FingerPrintHash)
|
cookie.SetSession(gc, authToken.FingerPrintHash)
|
||||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash)
|
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash, authToken.SessionTokenExpiresAt)
|
||||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token)
|
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token, authToken.AccessToken.ExpiresAt)
|
||||||
|
|
||||||
if authToken.RefreshToken != nil {
|
if authToken.RefreshToken != nil {
|
||||||
res.RefreshToken = &authToken.RefreshToken.Token
|
res.RefreshToken = &authToken.RefreshToken.Token
|
||||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token)
|
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token, authToken.RefreshToken.ExpiresAt)
|
||||||
}
|
}
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,11 +55,11 @@ func validateJwtTokenTest(t *testing.T, s TestSetup) {
|
||||||
authToken, err := token.CreateAuthToken(gc, user, roles, scope, constants.AuthRecipeMethodBasicAuth, nonce, "")
|
authToken, err := token.CreateAuthToken(gc, user, roles, scope, constants.AuthRecipeMethodBasicAuth, nonce, "")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, authToken)
|
assert.NotNil(t, authToken)
|
||||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash)
|
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash, authToken.SessionTokenExpiresAt)
|
||||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token)
|
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token, authToken.AccessToken.ExpiresAt)
|
||||||
|
|
||||||
if authToken.RefreshToken != nil {
|
if authToken.RefreshToken != nil {
|
||||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token)
|
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token, authToken.RefreshToken.ExpiresAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run(`should validate the access token`, func(t *testing.T) {
|
t.Run(`should validate the access token`, func(t *testing.T) {
|
||||||
|
|
|
@ -31,7 +31,9 @@ type JWTToken struct {
|
||||||
// Token object to hold the finger print and refresh token information
|
// Token object to hold the finger print and refresh token information
|
||||||
type Token struct {
|
type Token struct {
|
||||||
FingerPrint string `json:"fingerprint"`
|
FingerPrint string `json:"fingerprint"`
|
||||||
|
// Session Token
|
||||||
FingerPrintHash string `json:"fingerprint_hash"`
|
FingerPrintHash string `json:"fingerprint_hash"`
|
||||||
|
SessionTokenExpiresAt int64 `json:"expires_at"`
|
||||||
RefreshToken *JWTToken `json:"refresh_token"`
|
RefreshToken *JWTToken `json:"refresh_token"`
|
||||||
AccessToken *JWTToken `json:"access_token"`
|
AccessToken *JWTToken `json:"access_token"`
|
||||||
IDToken *JWTToken `json:"id_token"`
|
IDToken *JWTToken `json:"id_token"`
|
||||||
|
@ -51,7 +53,7 @@ type SessionData struct {
|
||||||
// CreateAuthToken creates a new auth token when userlogs in
|
// CreateAuthToken creates a new auth token when userlogs in
|
||||||
func CreateAuthToken(gc *gin.Context, user models.User, roles, scope []string, loginMethod, nonce string, code string) (*Token, error) {
|
func CreateAuthToken(gc *gin.Context, user models.User, roles, scope []string, loginMethod, nonce string, code string) (*Token, error) {
|
||||||
hostname := parsers.GetHost(gc)
|
hostname := parsers.GetHost(gc)
|
||||||
_, fingerPrintHash, err := CreateSessionToken(user, nonce, roles, scope, loginMethod)
|
_, fingerPrintHash, sessionTokenExpiresAt, err := CreateSessionToken(user, nonce, roles, scope, loginMethod)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -84,6 +86,7 @@ func CreateAuthToken(gc *gin.Context, user models.User, roles, scope []string, l
|
||||||
res := &Token{
|
res := &Token{
|
||||||
FingerPrint: nonce,
|
FingerPrint: nonce,
|
||||||
FingerPrintHash: fingerPrintHash,
|
FingerPrintHash: fingerPrintHash,
|
||||||
|
SessionTokenExpiresAt: sessionTokenExpiresAt,
|
||||||
AccessToken: &JWTToken{Token: accessToken, ExpiresAt: accessTokenExpiresAt},
|
AccessToken: &JWTToken{Token: accessToken, ExpiresAt: accessTokenExpiresAt},
|
||||||
IDToken: &JWTToken{Token: idToken, ExpiresAt: idTokenExpiresAt},
|
IDToken: &JWTToken{Token: idToken, ExpiresAt: idTokenExpiresAt},
|
||||||
}
|
}
|
||||||
|
@ -101,7 +104,8 @@ func CreateAuthToken(gc *gin.Context, user models.User, roles, scope []string, l
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateSessionToken creates a new session token
|
// CreateSessionToken creates a new session token
|
||||||
func CreateSessionToken(user models.User, nonce string, roles, scope []string, loginMethod string) (*SessionData, string, error) {
|
func CreateSessionToken(user models.User, nonce string, roles, scope []string, loginMethod string) (*SessionData, string, int64, error) {
|
||||||
|
expiresAt := time.Now().AddDate(1, 0, 0).Unix()
|
||||||
fingerPrintMap := &SessionData{
|
fingerPrintMap := &SessionData{
|
||||||
Nonce: nonce,
|
Nonce: nonce,
|
||||||
Roles: roles,
|
Roles: roles,
|
||||||
|
@ -109,15 +113,15 @@ func CreateSessionToken(user models.User, nonce string, roles, scope []string, l
|
||||||
Scope: scope,
|
Scope: scope,
|
||||||
LoginMethod: loginMethod,
|
LoginMethod: loginMethod,
|
||||||
IssuedAt: time.Now().Unix(),
|
IssuedAt: time.Now().Unix(),
|
||||||
ExpiresAt: time.Now().AddDate(1, 0, 0).Unix(),
|
ExpiresAt: expiresAt,
|
||||||
}
|
}
|
||||||
fingerPrintBytes, _ := json.Marshal(fingerPrintMap)
|
fingerPrintBytes, _ := json.Marshal(fingerPrintMap)
|
||||||
fingerPrintHash, err := crypto.EncryptAES(string(fingerPrintBytes))
|
fingerPrintHash, err := crypto.EncryptAES(string(fingerPrintBytes))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return fingerPrintMap, fingerPrintHash, nil
|
return fingerPrintMap, fingerPrintHash, expiresAt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateRefreshToken util to create JWT token
|
// CreateRefreshToken util to create JWT token
|
||||||
|
|
Loading…
Reference in New Issue
Block a user