fix: move sessionstore -> memstore

This commit is contained in:
Lakhan Samani 2022-05-27 23:20:38 +05:30
parent 7b13034081
commit 1941cf4299
38 changed files with 451 additions and 400 deletions

View File

@ -9,7 +9,7 @@ import (
"github.com/authorizerdev/authorizer/server/db/providers/cassandradb"
"github.com/authorizerdev/authorizer/server/db/providers/mongodb"
"github.com/authorizerdev/authorizer/server/db/providers/sql"
"github.com/authorizerdev/authorizer/server/envstore"
"github.com/authorizerdev/authorizer/server/memorystore"
)
// Provider returns the current database provider
@ -18,13 +18,15 @@ var Provider providers.Provider
func InitDB() error {
var err error
isSQL := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) != constants.DbTypeArangodb && envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) != constants.DbTypeMongodb && envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) != constants.DbTypeCassandraDB
isArangoDB := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) == constants.DbTypeArangodb
isMongoDB := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) == constants.DbTypeMongodb
isCassandra := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) == constants.DbTypeCassandraDB
envs := memorystore.RequiredEnvStoreObj.GetRequiredEnv()
isSQL := envs.DatabaseType != constants.DbTypeArangodb && envs.DatabaseType != constants.DbTypeMongodb && envs.DatabaseType != constants.DbTypeCassandraDB
isArangoDB := envs.DatabaseType == constants.DbTypeArangodb
isMongoDB := envs.DatabaseType == constants.DbTypeMongodb
isCassandra := envs.DatabaseType == constants.DbTypeCassandraDB
if isSQL {
log.Info("Initializing SQL Driver for: ", envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType))
log.Info("Initializing SQL Driver for: ", envs.DatabaseType)
Provider, err = sql.NewProvider()
if err != nil {
log.Fatal("Failed to initialize SQL driver: ", err)

76
server/env/env.go vendored
View File

@ -6,7 +6,6 @@ import (
"strings"
"github.com/google/uuid"
"github.com/joho/godotenv"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/constants"
@ -15,81 +14,6 @@ import (
"github.com/authorizerdev/authorizer/server/utils"
)
// InitRequiredEnv to initialize EnvData and through error if required env are not present
func InitRequiredEnv() error {
envPath := os.Getenv(constants.EnvKeyEnvPath)
if envPath == "" {
envPath = envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyEnvPath)
if envPath == "" {
envPath = `.env`
}
}
if envstore.ARG_ENV_FILE != nil && *envstore.ARG_ENV_FILE != "" {
envPath = *envstore.ARG_ENV_FILE
}
log.Info("env path: ", envPath)
err := godotenv.Load(envPath)
if err != nil {
log.Info("using OS env instead of %s file", envPath)
}
dbURL := os.Getenv(constants.EnvKeyDatabaseURL)
dbType := os.Getenv(constants.EnvKeyDatabaseType)
dbName := os.Getenv(constants.EnvKeyDatabaseName)
dbPort := os.Getenv(constants.EnvKeyDatabasePort)
dbHost := os.Getenv(constants.EnvKeyDatabaseHost)
dbUsername := os.Getenv(constants.EnvKeyDatabaseUsername)
dbPassword := os.Getenv(constants.EnvKeyDatabasePassword)
dbCert := os.Getenv(constants.EnvKeyDatabaseCert)
dbCertKey := os.Getenv(constants.EnvKeyDatabaseCertKey)
dbCACert := os.Getenv(constants.EnvKeyDatabaseCACert)
if strings.TrimSpace(dbType) == "" {
if envstore.ARG_DB_TYPE != nil && *envstore.ARG_DB_TYPE != "" {
dbType = strings.TrimSpace(*envstore.ARG_DB_TYPE)
}
if dbType == "" {
log.Debug("DATABASE_TYPE is not set")
return errors.New("invalid database type. DATABASE_TYPE is empty")
}
}
if strings.TrimSpace(dbURL) == "" && envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL) == "" {
if envstore.ARG_DB_URL != nil && *envstore.ARG_DB_URL != "" {
dbURL = strings.TrimSpace(*envstore.ARG_DB_URL)
}
if dbURL == "" && dbPort == "" && dbHost == "" && dbUsername == "" && dbPassword == "" {
log.Debug("DATABASE_URL is not set")
return errors.New("invalid database url. DATABASE_URL is required")
}
}
if dbName == "" {
if dbName == "" {
dbName = "authorizer"
}
}
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyEnvPath, envPath)
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseURL, dbURL)
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseType, dbType)
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseName, dbName)
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseHost, dbHost)
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabasePort, dbPort)
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseUsername, dbUsername)
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabasePassword, dbPassword)
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseCert, dbCert)
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseCertKey, dbCertKey)
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseCACert, dbCACert)
return nil
}
// InitEnv to initialize EnvData and through error if required env are not present
func InitAllEnv() error {
envData, err := GetEnvData()

View File

@ -6,17 +6,6 @@ import (
"github.com/authorizerdev/authorizer/server/constants"
)
var (
// ARG_DB_URL is the cli arg variable for the database url
ARG_DB_URL *string
// ARG_DB_TYPE is the cli arg variable for the database type
ARG_DB_TYPE *string
// ARG_ENV_FILE is the cli arg variable for the env file
ARG_ENV_FILE *string
// ARG_LOG_LEVEL is the cli arg variable for the log level
ARG_LOG_LEVEL *string
)
// Store data structure
type Store struct {
StringEnv map[string]string `json:"string_env"`

View File

@ -14,7 +14,7 @@ import (
"github.com/authorizerdev/authorizer/server/cookie"
"github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/envstore"
"github.com/authorizerdev/authorizer/server/sessionstore"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/token"
)
@ -223,7 +223,10 @@ func AuthorizeHandler() gin.HandlerFunc {
// based on the response type, generate the response
if isResponseTypeCode {
// rollover the session for security
sessionstore.RemoveState(sessionToken)
err = memorystore.Provider.RemoveState(sessionToken)
if err != nil {
log.Debug("Failed to remove state: ", err)
}
nonce := uuid.New().String()
newSessionTokenData, newSessionToken, err := token.CreateSessionToken(user, nonce, claims.Roles, scope)
if err != nil {
@ -244,10 +247,10 @@ func AuthorizeHandler() gin.HandlerFunc {
return
}
sessionstore.SetState(newSessionToken, newSessionTokenData.Nonce+"@"+user.ID)
memorystore.Provider.SetState(newSessionToken, newSessionTokenData.Nonce+"@"+user.ID)
cookie.SetSession(gc, newSessionToken)
code := uuid.New().String()
sessionstore.SetState(codeChallenge, code+"@"+newSessionToken)
memorystore.Provider.SetState(codeChallenge, code+"@"+newSessionToken)
gc.HTML(http.StatusOK, template, gin.H{
"target_origin": redirectURI,
"authorization_response": map[string]interface{}{
@ -281,9 +284,9 @@ func AuthorizeHandler() gin.HandlerFunc {
}
return
}
sessionstore.RemoveState(sessionToken)
sessionstore.SetState(authToken.FingerPrintHash, authToken.FingerPrint+"@"+user.ID)
sessionstore.SetState(authToken.AccessToken.Token, authToken.FingerPrint+"@"+user.ID)
memorystore.Provider.RemoveState(sessionToken)
memorystore.Provider.SetState(authToken.FingerPrintHash, authToken.FingerPrint+"@"+user.ID)
memorystore.Provider.SetState(authToken.AccessToken.Token, authToken.FingerPrint+"@"+user.ID)
cookie.SetSession(gc, authToken.FingerPrintHash)
expiresIn := authToken.AccessToken.ExpiresAt - time.Now().Unix()
@ -306,7 +309,7 @@ func AuthorizeHandler() gin.HandlerFunc {
if authToken.RefreshToken != nil {
res["refresh_token"] = authToken.RefreshToken.Token
params += "&refresh_token=" + authToken.RefreshToken.Token
sessionstore.SetState(authToken.RefreshToken.Token, authToken.FingerPrint+"@"+user.ID)
memorystore.Provider.SetState(authToken.RefreshToken.Token, authToken.FingerPrint+"@"+user.ID)
}
if isQuery {

View File

@ -9,7 +9,7 @@ import (
"github.com/authorizerdev/authorizer/server/cookie"
"github.com/authorizerdev/authorizer/server/crypto"
"github.com/authorizerdev/authorizer/server/sessionstore"
"github.com/authorizerdev/authorizer/server/memorystore"
)
// Handler to logout user
@ -37,7 +37,10 @@ func LogoutHandler() gin.HandlerFunc {
fingerPrint := string(decryptedFingerPrint)
sessionstore.RemoveState(fingerPrint)
err = memorystore.Provider.RemoveState(fingerPrint)
if err != nil {
log.Debug("Failed to remove state: ", err)
}
cookie.DeleteSession(gc)
if redirectURL != "" {

View File

@ -20,8 +20,8 @@ import (
"github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/db/models"
"github.com/authorizerdev/authorizer/server/envstore"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/oauth"
"github.com/authorizerdev/authorizer/server/sessionstore"
"github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils"
)
@ -32,12 +32,12 @@ func OAuthCallbackHandler() gin.HandlerFunc {
provider := c.Param("oauth_provider")
state := c.Request.FormValue("state")
sessionState := sessionstore.GetState(state)
sessionState := memorystore.Provider.GetState(state)
if sessionState == "" {
log.Debug("Invalid oauth state: ", state)
c.JSON(400, gin.H{"error": "invalid oauth state"})
}
sessionstore.GetState(state)
memorystore.Provider.GetState(state)
// contains random token, redirect url, role
sessionSplit := strings.Split(state, "___")
@ -178,12 +178,12 @@ func OAuthCallbackHandler() gin.HandlerFunc {
params := "access_token=" + authToken.AccessToken.Token + "&token_type=bearer&expires_in=" + strconv.FormatInt(expiresIn, 10) + "&state=" + stateValue + "&id_token=" + authToken.IDToken.Token
cookie.SetSession(c, authToken.FingerPrintHash)
sessionstore.SetState(authToken.FingerPrintHash, authToken.FingerPrint+"@"+user.ID)
sessionstore.SetState(authToken.AccessToken.Token, authToken.FingerPrint+"@"+user.ID)
memorystore.Provider.SetState(authToken.FingerPrintHash, authToken.FingerPrint+"@"+user.ID)
memorystore.Provider.SetState(authToken.AccessToken.Token, authToken.FingerPrint+"@"+user.ID)
if authToken.RefreshToken != nil {
params = params + `&refresh_token=` + authToken.RefreshToken.Token
sessionstore.SetState(authToken.RefreshToken.Token, authToken.FingerPrint+"@"+user.ID)
memorystore.Provider.SetState(authToken.RefreshToken.Token, authToken.FingerPrint+"@"+user.ID)
}
go db.Provider.AddSession(models.Session{

View File

@ -9,8 +9,8 @@ import (
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/envstore"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/oauth"
"github.com/authorizerdev/authorizer/server/sessionstore"
"github.com/authorizerdev/authorizer/server/utils"
)
@ -78,7 +78,7 @@ func OAuthLoginHandler() gin.HandlerFunc {
isProviderConfigured = false
break
}
sessionstore.SetState(oauthStateString, constants.SignupMethodGoogle)
memorystore.Provider.SetState(oauthStateString, constants.SignupMethodGoogle)
// during the init of OAuthProvider authorizer url might be empty
oauth.OAuthProviders.GoogleConfig.RedirectURL = hostname + "/oauth_callback/google"
url := oauth.OAuthProviders.GoogleConfig.AuthCodeURL(oauthStateString)
@ -89,7 +89,7 @@ func OAuthLoginHandler() gin.HandlerFunc {
isProviderConfigured = false
break
}
sessionstore.SetState(oauthStateString, constants.SignupMethodGithub)
memorystore.Provider.SetState(oauthStateString, constants.SignupMethodGithub)
oauth.OAuthProviders.GithubConfig.RedirectURL = hostname + "/oauth_callback/github"
url := oauth.OAuthProviders.GithubConfig.AuthCodeURL(oauthStateString)
c.Redirect(http.StatusTemporaryRedirect, url)
@ -99,7 +99,7 @@ func OAuthLoginHandler() gin.HandlerFunc {
isProviderConfigured = false
break
}
sessionstore.SetState(oauthStateString, constants.SignupMethodFacebook)
memorystore.Provider.SetState(oauthStateString, constants.SignupMethodFacebook)
oauth.OAuthProviders.FacebookConfig.RedirectURL = hostname + "/oauth_callback/facebook"
url := oauth.OAuthProviders.FacebookConfig.AuthCodeURL(oauthStateString)
c.Redirect(http.StatusTemporaryRedirect, url)

View File

@ -9,7 +9,7 @@ import (
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/envstore"
"github.com/authorizerdev/authorizer/server/sessionstore"
"github.com/authorizerdev/authorizer/server/memorystore"
)
// Revoke handler to revoke refresh token
@ -46,7 +46,7 @@ func RevokeHandler() gin.HandlerFunc {
return
}
sessionstore.RemoveState(refreshToken)
memorystore.Provider.RemoveState(refreshToken)
gc.JSON(http.StatusOK, gin.H{
"message": "Token revoked successfully",

View File

@ -14,7 +14,7 @@ import (
"github.com/authorizerdev/authorizer/server/cookie"
"github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/envstore"
"github.com/authorizerdev/authorizer/server/sessionstore"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/token"
)
@ -98,7 +98,7 @@ func TokenHandler() gin.HandlerFunc {
encryptedCode := strings.ReplaceAll(base64.URLEncoding.EncodeToString(hash.Sum(nil)), "+", "-")
encryptedCode = strings.ReplaceAll(encryptedCode, "/", "_")
encryptedCode = strings.ReplaceAll(encryptedCode, "=", "")
sessionData := sessionstore.GetState(encryptedCode)
sessionData := memorystore.Provider.GetState(encryptedCode)
if sessionData == "" {
log.Debug("Session data is empty")
gc.JSON(http.StatusBadRequest, gin.H{
@ -132,7 +132,7 @@ func TokenHandler() gin.HandlerFunc {
return
}
// rollover the session for security
sessionstore.RemoveState(sessionDataSplit[1])
memorystore.Provider.RemoveState(sessionDataSplit[1])
userID = claims.Subject
roles = claims.Roles
scope = claims.Scope
@ -164,7 +164,7 @@ func TokenHandler() gin.HandlerFunc {
scope = append(scope, v.(string))
}
// remove older refresh token and rotate it for security
sessionstore.RemoveState(refreshToken)
memorystore.Provider.RemoveState(refreshToken)
}
user, err := db.Provider.GetUserByID(userID)
@ -186,8 +186,8 @@ func TokenHandler() gin.HandlerFunc {
})
return
}
sessionstore.SetState(authToken.FingerPrintHash, authToken.FingerPrint+"@"+user.ID)
sessionstore.SetState(authToken.AccessToken.Token, authToken.FingerPrint+"@"+user.ID)
memorystore.Provider.SetState(authToken.FingerPrintHash, authToken.FingerPrint+"@"+user.ID)
memorystore.Provider.SetState(authToken.AccessToken.Token, authToken.FingerPrint+"@"+user.ID)
cookie.SetSession(gc, authToken.FingerPrintHash)
expiresIn := authToken.AccessToken.ExpiresAt - time.Now().Unix()
@ -205,7 +205,7 @@ func TokenHandler() gin.HandlerFunc {
if authToken.RefreshToken != nil {
res["refresh_token"] = authToken.RefreshToken.Token
sessionstore.SetState(authToken.RefreshToken.Token, authToken.FingerPrint+"@"+user.ID)
memorystore.Provider.SetState(authToken.RefreshToken.Token, authToken.FingerPrint+"@"+user.ID)
}
gc.JSON(http.StatusOK, res)

View File

@ -12,7 +12,7 @@ import (
"github.com/authorizerdev/authorizer/server/cookie"
"github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/db/models"
"github.com/authorizerdev/authorizer/server/sessionstore"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils"
)
@ -99,12 +99,12 @@ func VerifyEmailHandler() gin.HandlerFunc {
params := "access_token=" + authToken.AccessToken.Token + "&token_type=bearer&expires_in=" + strconv.FormatInt(expiresIn, 10) + "&state=" + state + "&id_token=" + authToken.IDToken.Token
cookie.SetSession(c, authToken.FingerPrintHash)
sessionstore.SetState(authToken.FingerPrintHash, authToken.FingerPrint+"@"+user.ID)
sessionstore.SetState(authToken.AccessToken.Token, authToken.FingerPrint+"@"+user.ID)
memorystore.Provider.SetState(authToken.FingerPrintHash, authToken.FingerPrint+"@"+user.ID)
memorystore.Provider.SetState(authToken.AccessToken.Token, authToken.FingerPrint+"@"+user.ID)
if authToken.RefreshToken != nil {
params = params + `&refresh_token=${refresh_token}`
sessionstore.SetState(authToken.RefreshToken.Token, authToken.FingerPrint+"@"+user.ID)
memorystore.Provider.SetState(authToken.RefreshToken.Token, authToken.FingerPrint+"@"+user.ID)
}
if redirectURL == "" {

View File

@ -10,9 +10,10 @@ import (
"github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/env"
"github.com/authorizerdev/authorizer/server/envstore"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/oauth"
"github.com/authorizerdev/authorizer/server/routes"
"github.com/authorizerdev/authorizer/server/sessionstore"
"github.com/authorizerdev/authorizer/server/utils"
)
var VERSION string
@ -27,23 +28,21 @@ func (u LogUTCFormatter) Format(e *log.Entry) ([]byte, error) {
}
func main() {
envstore.ARG_DB_URL = flag.String("database_url", "", "Database connection string")
envstore.ARG_DB_TYPE = flag.String("database_type", "", "Database type, possible values are postgres,mysql,sqlite")
envstore.ARG_ENV_FILE = flag.String("env_file", "", "Env file path")
envstore.ARG_LOG_LEVEL = flag.String("log_level", "info", "Log level, possible values are debug,info,warn,error,fatal,panic")
utils.ARG_DB_URL = flag.String("database_url", "", "Database connection string")
utils.ARG_DB_TYPE = flag.String("database_type", "", "Database type, possible values are postgres,mysql,sqlite")
utils.ARG_ENV_FILE = flag.String("env_file", "", "Env file path")
utils.ARG_LOG_LEVEL = flag.String("log_level", "info", "Log level, possible values are debug,info,warn,error,fatal,panic")
flag.Parse()
// global log level
logrus.SetFormatter(LogUTCFormatter{&logrus.JSONFormatter{}})
logrus.SetReportCaller(true)
// log instance for gin server
log := logrus.New()
log.SetFormatter(LogUTCFormatter{&logrus.JSONFormatter{}})
log.SetReportCaller(true)
var logLevel logrus.Level
switch *envstore.ARG_LOG_LEVEL {
switch *utils.ARG_LOG_LEVEL {
case "debug":
logLevel = logrus.DebugLevel
case "info":
@ -62,14 +61,26 @@ func main() {
logrus.SetLevel(logLevel)
log.SetLevel(logLevel)
// show file path in log for debug or other log levels.
if logLevel != logrus.InfoLevel {
logrus.SetReportCaller(true)
log.SetReportCaller(true)
}
constants.VERSION = VERSION
// initialize required envs (mainly db & env file path)
err := env.InitRequiredEnv()
// initialize required envs (mainly db, env file path and redis)
err := memorystore.InitRequiredEnv()
if err != nil {
log.Fatal("Error while initializing required envs: ", err)
}
// initialize memory store
err = memorystore.InitMemStore()
if err != nil {
log.Fatal("Error while initializing memory store: ", err)
}
// initialize db provider
err = db.InitDB()
if err != nil {
@ -89,12 +100,6 @@ func main() {
log.Fatalln("Error while persisting env: ", err)
}
// initialize session store (redis or in-memory based on env)
err = sessionstore.InitSession()
if err != nil {
log.Fatalln("Error while initializing session store: ", err)
}
// initialize oauth providers based on env
err = oauth.InitOAuth()
if err != nil {

View File

@ -0,0 +1,36 @@
package memorystore
import (
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/memorystore/providers"
"github.com/authorizerdev/authorizer/server/memorystore/providers/inmemory"
"github.com/authorizerdev/authorizer/server/memorystore/providers/redis"
)
// Provider returns the current database provider
var Provider providers.Provider
// InitMemStore initializes the memory store
func InitMemStore() error {
var err error
redisURL := RequiredEnvStoreObj.GetRequiredEnv().RedisURL
if redisURL != "" {
log.Info("Initializing Redis memory store")
Provider, err = redis.NewRedisProvider(redisURL)
if err != nil {
return err
}
return nil
}
log.Info("using in memory store to save sessions")
// if redis url is not set use in memory store
Provider, err = inmemory.NewInMemoryProvider()
if err != nil {
return err
}
return nil
}

View File

@ -1,26 +1,18 @@
package sessionstore
package inmemory
import (
"strings"
"sync"
)
// InMemoryStore is a simple in-memory store for sessions.
type InMemoryStore struct {
mutex sync.Mutex
sessionStore map[string]map[string]string
stateStore map[string]string
}
import "strings"
// ClearStore clears the in-memory store.
func (c *InMemoryStore) ClearStore() {
func (c *provider) ClearStore() error {
c.mutex.Lock()
defer c.mutex.Unlock()
c.sessionStore = map[string]map[string]string{}
return nil
}
// GetUserSessions returns all the user session token from the in-memory store.
func (c *InMemoryStore) GetUserSessions(userId string) map[string]string {
func (c *provider) GetUserSessions(userId string) map[string]string {
// c.mutex.Lock()
// defer c.mutex.Unlock()
res := map[string]string{}
@ -35,25 +27,29 @@ func (c *InMemoryStore) GetUserSessions(userId string) map[string]string {
}
// DeleteAllUserSession deletes all the user sessions from in-memory store.
func (c *InMemoryStore) DeleteAllUserSession(userId string) {
func (c *provider) DeleteAllUserSession(userId string) error {
// c.mutex.Lock()
// defer c.mutex.Unlock()
sessions := GetUserSessions(userId)
sessions := c.GetUserSessions(userId)
for k := range sessions {
RemoveState(k)
c.RemoveState(k)
}
return nil
}
// SetState sets the state in the in-memory store.
func (c *InMemoryStore) SetState(key, state string) {
func (c *provider) SetState(key, state string) error {
c.mutex.Lock()
defer c.mutex.Unlock()
c.stateStore[key] = state
return nil
}
// GetState gets the state from the in-memory store.
func (c *InMemoryStore) GetState(key string) string {
func (c *provider) GetState(key string) string {
c.mutex.Lock()
defer c.mutex.Unlock()
@ -66,9 +62,11 @@ func (c *InMemoryStore) GetState(key string) string {
}
// RemoveState removes the state from the in-memory store.
func (c *InMemoryStore) RemoveState(key string) {
func (c *provider) RemoveState(key string) error {
c.mutex.Lock()
defer c.mutex.Unlock()
delete(c.stateStore, key)
return nil
}

View File

@ -0,0 +1,18 @@
package inmemory
import "sync"
type provider struct {
mutex sync.Mutex
sessionStore map[string]map[string]string
stateStore map[string]string
}
// NewInMemoryStore returns a new in-memory store.
func NewInMemoryProvider() (*provider, error) {
return &provider{
mutex: sync.Mutex{},
sessionStore: map[string]map[string]string{},
stateStore: map[string]string{},
}, nil
}

View File

@ -0,0 +1,17 @@
package providers
// Provider defines current memory store provider
type Provider interface {
// DeleteAllSessions deletes all the sessions from the session store
DeleteAllUserSession(userId string) error
// GetUserSessions returns all the user sessions from the session store
GetUserSessions(userId string) map[string]string
// ClearStore clears the session store for authorizer tokens
ClearStore() error
// SetState sets the login state (key, value form) in the session store
SetState(key, state string) error
// GetState returns the state from the session store
GetState(key string) string
// RemoveState removes the social login state from the session store
RemoveState(key string) error
}

View File

@ -0,0 +1,75 @@
package redis
import (
"context"
"strings"
"time"
"github.com/go-redis/redis/v8"
log "github.com/sirupsen/logrus"
)
// RedisClient is the interface for redis client & redis cluster client
type RedisClient interface {
HMSet(ctx context.Context, key string, values ...interface{}) *redis.BoolCmd
Del(ctx context.Context, keys ...string) *redis.IntCmd
HDel(ctx context.Context, key string, fields ...string) *redis.IntCmd
HMGet(ctx context.Context, key string, fields ...string) *redis.SliceCmd
HGetAll(ctx context.Context, key string) *redis.StringStringMapCmd
Set(ctx context.Context, key string, value interface{}, expiration time.Duration) *redis.StatusCmd
Get(ctx context.Context, key string) *redis.StringCmd
}
type provider struct {
ctx context.Context
store RedisClient
}
// NewRedisProvider returns a new redis provider
func NewRedisProvider(redisURL string) (*provider, error) {
redisURLHostPortsList := strings.Split(redisURL, ",")
if len(redisURLHostPortsList) > 1 {
opt, err := redis.ParseURL(redisURLHostPortsList[0])
if err != nil {
log.Debug("error parsing redis url: ", err)
return nil, err
}
urls := []string{opt.Addr}
urlList := redisURLHostPortsList[1:]
urls = append(urls, urlList...)
clusterOpt := &redis.ClusterOptions{Addrs: urls}
rdb := redis.NewClusterClient(clusterOpt)
ctx := context.Background()
_, err = rdb.Ping(ctx).Result()
if err != nil {
log.Debug("error connecting to redis: ", err)
return nil, err
}
return &provider{
ctx: ctx,
store: rdb,
}, nil
}
opt, err := redis.ParseURL(redisURL)
if err != nil {
log.Debug("error parsing redis url: ", err)
return nil, err
}
rdb := redis.NewClient(opt)
ctx := context.Background()
_, err = rdb.Ping(ctx).Result()
if err != nil {
log.Debug("error connecting to redis: ", err)
return nil, err
}
return &provider{
ctx: ctx,
store: rdb,
}, nil
}

View File

@ -1,27 +1,24 @@
package sessionstore
package redis
import (
"context"
"strings"
log "github.com/sirupsen/logrus"
)
type RedisStore struct {
ctx context.Context
store RedisSessionClient
}
// ClearStore clears the redis store for authorizer related tokens
func (c *RedisStore) ClearStore() {
func (c *provider) ClearStore() error {
err := c.store.Del(c.ctx, "authorizer_*").Err()
if err != nil {
log.Debug("Error clearing redis store: ", err)
return err
}
return nil
}
// GetUserSessions returns all the user session token from the redis store.
func (c *RedisStore) GetUserSessions(userID string) map[string]string {
func (c *provider) GetUserSessions(userID string) map[string]string {
data, err := c.store.HGetAll(c.ctx, "*").Result()
if err != nil {
log.Debug("error getting token from redis store: ", err)
@ -39,28 +36,34 @@ func (c *RedisStore) GetUserSessions(userID string) map[string]string {
}
// DeleteAllUserSession deletes all the user session from redis
func (c *RedisStore) DeleteAllUserSession(userId string) {
sessions := GetUserSessions(userId)
func (c *provider) DeleteAllUserSession(userId string) error {
sessions := c.GetUserSessions(userId)
for k, v := range sessions {
if k == "token" {
err := c.store.Del(c.ctx, v)
err := c.store.Del(c.ctx, v).Err()
if err != nil {
log.Debug("Error deleting redis token: ", err)
return err
}
}
}
return nil
}
// SetState sets the state in redis store.
func (c *RedisStore) SetState(key, value string) {
func (c *provider) SetState(key, value string) error {
err := c.store.Set(c.ctx, "authorizer_"+key, value, 0).Err()
if err != nil {
log.Debug("Error saving redis token: ", err)
return err
}
return nil
}
// GetState gets the state from redis store.
func (c *RedisStore) GetState(key string) string {
func (c *provider) GetState(key string) string {
state := ""
state, err := c.store.Get(c.ctx, "authorizer_"+key).Result()
if err != nil {
@ -71,9 +74,12 @@ func (c *RedisStore) GetState(key string) string {
}
// RemoveState removes the state from redis store.
func (c *RedisStore) RemoveState(key string) {
func (c *provider) RemoveState(key string) error {
err := c.store.Del(c.ctx, "authorizer_"+key).Err()
if err != nil {
log.Fatalln("Error deleting redis token: ", err)
return err
}
return nil
}

View File

@ -0,0 +1,136 @@
package memorystore
import (
"errors"
"os"
"strings"
"sync"
"github.com/joho/godotenv"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/envstore"
"github.com/authorizerdev/authorizer/server/utils"
)
// RequiredEnv holds information about required envs
type RequiredEnv struct {
EnvPath string
DatabaseURL string
DatabaseType string
DatabaseName string
DatabaseHost string
DatabasePort string
DatabaseUsername string
DatabasePassword string
DatabaseCert string
DatabaseCertKey string
DatabaseCACert string
RedisURL string
}
// RequiredEnvObj is a simple in-memory store for sessions.
type RequiredEnvStore struct {
mutex sync.Mutex
requiredEnv RequiredEnv
}
// GetRequiredEnv to get required env
func (r *RequiredEnvStore) GetRequiredEnv() RequiredEnv {
r.mutex.Lock()
defer r.mutex.Unlock()
return r.requiredEnv
}
// SetRequiredEnv to set required env
func (r *RequiredEnvStore) SetRequiredEnv(requiredEnv RequiredEnv) {
r.mutex.Lock()
defer r.mutex.Unlock()
r.requiredEnv = requiredEnv
}
var RequiredEnvStoreObj *RequiredEnvStore
// InitRequiredEnv to initialize EnvData and through error if required env are not present
func InitRequiredEnv() error {
envPath := os.Getenv(constants.EnvKeyEnvPath)
if envPath == "" {
if envPath == "" {
envPath = `.env`
}
}
if utils.ARG_ENV_FILE != nil && *utils.ARG_ENV_FILE != "" {
envPath = *utils.ARG_ENV_FILE
}
log.Info("env path: ", envPath)
err := godotenv.Load(envPath)
if err != nil {
log.Info("using OS env instead of %s file", envPath)
}
dbURL := os.Getenv(constants.EnvKeyDatabaseURL)
dbType := os.Getenv(constants.EnvKeyDatabaseType)
dbName := os.Getenv(constants.EnvKeyDatabaseName)
dbPort := os.Getenv(constants.EnvKeyDatabasePort)
dbHost := os.Getenv(constants.EnvKeyDatabaseHost)
dbUsername := os.Getenv(constants.EnvKeyDatabaseUsername)
dbPassword := os.Getenv(constants.EnvKeyDatabasePassword)
dbCert := os.Getenv(constants.EnvKeyDatabaseCert)
dbCertKey := os.Getenv(constants.EnvKeyDatabaseCertKey)
dbCACert := os.Getenv(constants.EnvKeyDatabaseCACert)
redisURL := os.Getenv(constants.EnvKeyRedisURL)
if strings.TrimSpace(dbType) == "" {
if utils.ARG_DB_TYPE != nil && *utils.ARG_DB_TYPE != "" {
dbType = strings.TrimSpace(*utils.ARG_DB_TYPE)
}
if dbType == "" {
log.Debug("DATABASE_TYPE is not set")
return errors.New("invalid database type. DATABASE_TYPE is empty")
}
}
if strings.TrimSpace(dbURL) == "" && envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL) == "" {
if utils.ARG_DB_URL != nil && *utils.ARG_DB_URL != "" {
dbURL = strings.TrimSpace(*utils.ARG_DB_URL)
}
if dbURL == "" && dbPort == "" && dbHost == "" && dbUsername == "" && dbPassword == "" {
log.Debug("DATABASE_URL is not set")
return errors.New("invalid database url. DATABASE_URL is required")
}
}
if dbName == "" {
if dbName == "" {
dbName = "authorizer"
}
}
requiredEnv := RequiredEnv{
EnvPath: envPath,
DatabaseURL: dbURL,
DatabaseType: dbType,
DatabaseName: dbName,
DatabaseHost: dbHost,
DatabasePort: dbPort,
DatabaseUsername: dbUsername,
DatabasePassword: dbPassword,
DatabaseCert: dbCert,
DatabaseCertKey: dbCertKey,
DatabaseCACert: dbCACert,
RedisURL: redisURL,
}
RequiredEnvStoreObj = &RequiredEnvStore{
requiredEnv: requiredEnv,
}
return nil
}

View File

@ -8,7 +8,7 @@ import (
"github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/sessionstore"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils"
)
@ -38,7 +38,7 @@ func DeleteUserResolver(ctx context.Context, params model.DeleteUserInput) (*mod
return res, err
}
go sessionstore.DeleteAllUserSession(fmt.Sprintf("%x", user.ID))
go memorystore.Provider.DeleteAllUserSession(fmt.Sprintf("%x", user.ID))
err = db.Provider.DeleteUser(user)
if err != nil {

View File

@ -15,7 +15,7 @@ import (
"github.com/authorizerdev/authorizer/server/db/models"
"github.com/authorizerdev/authorizer/server/envstore"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/sessionstore"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils"
)
@ -102,12 +102,12 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
}
cookie.SetSession(gc, authToken.FingerPrintHash)
sessionstore.SetState(authToken.FingerPrintHash, authToken.FingerPrint+"@"+user.ID)
sessionstore.SetState(authToken.AccessToken.Token, authToken.FingerPrint+"@"+user.ID)
memorystore.Provider.SetState(authToken.FingerPrintHash, authToken.FingerPrint+"@"+user.ID)
memorystore.Provider.SetState(authToken.AccessToken.Token, authToken.FingerPrint+"@"+user.ID)
if authToken.RefreshToken != nil {
res.RefreshToken = &authToken.RefreshToken.Token
sessionstore.SetState(authToken.RefreshToken.Token, authToken.FingerPrint+"@"+user.ID)
memorystore.Provider.SetState(authToken.RefreshToken.Token, authToken.FingerPrint+"@"+user.ID)
}
go db.Provider.AddSession(models.Session{

View File

@ -8,7 +8,7 @@ import (
"github.com/authorizerdev/authorizer/server/cookie"
"github.com/authorizerdev/authorizer/server/crypto"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/sessionstore"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/utils"
)
@ -37,7 +37,7 @@ func LogoutResolver(ctx context.Context) (*model.Response, error) {
fingerPrint := string(decryptedFingerPrint)
sessionstore.RemoveState(fingerPrint)
memorystore.Provider.RemoveState(fingerPrint)
cookie.DeleteSession(gc)
res = &model.Response{

View File

@ -4,12 +4,12 @@ import (
"context"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/sessionstore"
"github.com/authorizerdev/authorizer/server/memorystore"
)
// RevokeResolver resolver to revoke refresh token
func RevokeResolver(ctx context.Context, params model.OAuthRevokeInput) (*model.Response, error) {
sessionstore.RemoveState(params.RefreshToken)
memorystore.Provider.RemoveState(params.RefreshToken)
return &model.Response{
Message: "Token revoked",
}, nil

View File

@ -9,7 +9,7 @@ import (
"github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/sessionstore"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils"
)
@ -47,7 +47,7 @@ func RevokeAccessResolver(ctx context.Context, params model.UpdateAccessInput) (
return res, err
}
go sessionstore.DeleteAllUserSession(fmt.Sprintf("%x", user.ID))
go memorystore.Provider.DeleteAllUserSession(fmt.Sprintf("%x", user.ID))
res = &model.Response{
Message: `user access revoked successfully`,

View File

@ -11,7 +11,7 @@ import (
"github.com/authorizerdev/authorizer/server/cookie"
"github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/sessionstore"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils"
)
@ -76,9 +76,9 @@ func SessionResolver(ctx context.Context, params *model.SessionQueryInput) (*mod
}
// rollover the session for security
sessionstore.RemoveState(sessionToken)
sessionstore.SetState(authToken.FingerPrintHash, authToken.FingerPrint+"@"+user.ID)
sessionstore.SetState(authToken.AccessToken.Token, authToken.FingerPrint+"@"+user.ID)
memorystore.Provider.RemoveState(sessionToken)
memorystore.Provider.SetState(authToken.FingerPrintHash, authToken.FingerPrint+"@"+user.ID)
memorystore.Provider.SetState(authToken.AccessToken.Token, authToken.FingerPrint+"@"+user.ID)
cookie.SetSession(gc, authToken.FingerPrintHash)
expiresIn := authToken.AccessToken.ExpiresAt - time.Now().Unix()
@ -96,7 +96,7 @@ func SessionResolver(ctx context.Context, params *model.SessionQueryInput) (*mod
if authToken.RefreshToken != nil {
res.RefreshToken = &authToken.RefreshToken.Token
sessionstore.SetState(authToken.RefreshToken.Token, authToken.FingerPrint+"@"+user.ID)
memorystore.Provider.SetState(authToken.RefreshToken.Token, authToken.FingerPrint+"@"+user.ID)
}
return res, nil

View File

@ -16,7 +16,7 @@ import (
"github.com/authorizerdev/authorizer/server/email"
"github.com/authorizerdev/authorizer/server/envstore"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/sessionstore"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils"
)
@ -194,7 +194,7 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
return res, err
}
sessionstore.SetState(authToken.FingerPrintHash, authToken.FingerPrint+"@"+user.ID)
memorystore.Provider.SetState(authToken.FingerPrintHash, authToken.FingerPrint+"@"+user.ID)
cookie.SetSession(gc, authToken.FingerPrintHash)
go db.Provider.AddSession(models.Session{
UserID: user.ID,

View File

@ -16,7 +16,6 @@ import (
"github.com/authorizerdev/authorizer/server/envstore"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/oauth"
"github.com/authorizerdev/authorizer/server/sessionstore"
"github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils"
)
@ -214,11 +213,13 @@ func UpdateEnvResolver(ctx context.Context, params model.UpdateEnvInput) (*model
}
// updating jwk
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJWK, jwk)
err = sessionstore.InitSession()
if err != nil {
log.Debug("Failed to init session store: ", err)
return res, err
}
// TODO check how to update session store based on env change.
// err = sessionstore.InitSession()
// if err != nil {
// log.Debug("Failed to init session store: ", err)
// return res, err
// }
err = oauth.InitOAuth()
if err != nil {
return res, err

View File

@ -16,7 +16,7 @@ import (
"github.com/authorizerdev/authorizer/server/email"
"github.com/authorizerdev/authorizer/server/envstore"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/sessionstore"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils"
"golang.org/x/crypto/bcrypt"
@ -141,7 +141,7 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
return res, fmt.Errorf("user with this email address already exists")
}
go sessionstore.DeleteAllUserSession(user.ID)
go memorystore.Provider.DeleteAllUserSession(user.ID)
go cookie.DeleteSession(gc)
user.Email = newEmail

View File

@ -14,7 +14,7 @@ import (
"github.com/authorizerdev/authorizer/server/email"
"github.com/authorizerdev/authorizer/server/envstore"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/sessionstore"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils"
)
@ -112,7 +112,7 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
}
// TODO figure out how to do this
go sessionstore.DeleteAllUserSession(user.ID)
go memorystore.Provider.DeleteAllUserSession(user.ID)
hostname := utils.GetHost(gc)
user.Email = newEmail
@ -164,7 +164,7 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
rolesToSave = strings.Join(inputRoles, ",")
}
go sessionstore.DeleteAllUserSession(user.ID)
go memorystore.Provider.DeleteAllUserSession(user.ID)
}
if rolesToSave != "" {

View File

@ -10,7 +10,7 @@ import (
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/sessionstore"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils"
)
@ -38,7 +38,7 @@ func ValidateJwtTokenResolver(ctx context.Context, params model.ValidateJWTToken
nonce := ""
// access_token and refresh_token should be validated from session store as well
if tokenType == "access_token" || tokenType == "refresh_token" {
savedSession := sessionstore.GetState(params.Token)
savedSession := memorystore.Provider.GetState(params.Token)
if savedSession == "" {
return &model.ValidateJWTTokenResponse{
IsValid: false,

View File

@ -12,7 +12,7 @@ import (
"github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/db/models"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/sessionstore"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils"
)
@ -74,8 +74,8 @@ func VerifyEmailResolver(ctx context.Context, params model.VerifyEmailInput) (*m
return res, err
}
sessionstore.SetState(authToken.FingerPrintHash, authToken.FingerPrint+"@"+user.ID)
sessionstore.SetState(authToken.AccessToken.Token, authToken.FingerPrint+"@"+user.ID)
memorystore.Provider.SetState(authToken.FingerPrintHash, authToken.FingerPrint+"@"+user.ID)
memorystore.Provider.SetState(authToken.AccessToken.Token, authToken.FingerPrint+"@"+user.ID)
cookie.SetSession(gc, authToken.FingerPrintHash)
go db.Provider.AddSession(models.Session{
UserID: user.ID,

View File

@ -1,18 +0,0 @@
package sessionstore
import (
"context"
"time"
"github.com/go-redis/redis/v8"
)
type RedisSessionClient interface {
HMSet(ctx context.Context, key string, values ...interface{}) *redis.BoolCmd
Del(ctx context.Context, keys ...string) *redis.IntCmd
HDel(ctx context.Context, key string, fields ...string) *redis.IntCmd
HMGet(ctx context.Context, key string, fields ...string) *redis.SliceCmd
HGetAll(ctx context.Context, key string) *redis.StringStringMapCmd
Set(ctx context.Context, key string, value interface{}, expiration time.Duration) *redis.StatusCmd
Get(ctx context.Context, key string) *redis.StringCmd
}

View File

@ -1,156 +0,0 @@
package sessionstore
import (
"context"
"strings"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/envstore"
"github.com/go-redis/redis/v8"
)
// SessionStore is a struct that defines available session stores
// If redis store is available, higher preference is given to that store.
// Else in memory store is used.
type SessionStore struct {
InMemoryStoreObj *InMemoryStore
RedisMemoryStoreObj *RedisStore
}
// SessionStoreObj is a global variable that holds the
// reference to various session store instances
var SessionStoreObj SessionStore
// DeleteAllSessions deletes all the sessions from the session store
func DeleteAllUserSession(userId string) {
if SessionStoreObj.RedisMemoryStoreObj != nil {
SessionStoreObj.RedisMemoryStoreObj.DeleteAllUserSession(userId)
}
if SessionStoreObj.InMemoryStoreObj != nil {
SessionStoreObj.InMemoryStoreObj.DeleteAllUserSession(userId)
}
}
// GetUserSessions returns all the user sessions from the session store
func GetUserSessions(userId string) map[string]string {
if SessionStoreObj.RedisMemoryStoreObj != nil {
return SessionStoreObj.RedisMemoryStoreObj.GetUserSessions(userId)
}
if SessionStoreObj.InMemoryStoreObj != nil {
return SessionStoreObj.InMemoryStoreObj.GetUserSessions(userId)
}
return nil
}
// ClearStore clears the session store for authorizer tokens
func ClearStore() {
if SessionStoreObj.RedisMemoryStoreObj != nil {
SessionStoreObj.RedisMemoryStoreObj.ClearStore()
}
if SessionStoreObj.InMemoryStoreObj != nil {
SessionStoreObj.InMemoryStoreObj.ClearStore()
}
}
// SetState sets the login state (key, value form) in the session store
func SetState(key, state string) {
if SessionStoreObj.RedisMemoryStoreObj != nil {
SessionStoreObj.RedisMemoryStoreObj.SetState(key, state)
}
if SessionStoreObj.InMemoryStoreObj != nil {
SessionStoreObj.InMemoryStoreObj.SetState(key, state)
}
}
// GetState returns the state from the session store
func GetState(key string) string {
if SessionStoreObj.RedisMemoryStoreObj != nil {
return SessionStoreObj.RedisMemoryStoreObj.GetState(key)
}
if SessionStoreObj.InMemoryStoreObj != nil {
return SessionStoreObj.InMemoryStoreObj.GetState(key)
}
return ""
}
// RemoveState removes the social login state from the session store
func RemoveState(key string) {
if SessionStoreObj.RedisMemoryStoreObj != nil {
SessionStoreObj.RedisMemoryStoreObj.RemoveState(key)
}
if SessionStoreObj.InMemoryStoreObj != nil {
SessionStoreObj.InMemoryStoreObj.RemoveState(key)
}
}
// InitializeSessionStore initializes the SessionStoreObj based on environment variables
func InitSession() error {
if envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyRedisURL) != "" {
log.Info("using redis store to save sessions")
redisURL := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyRedisURL)
redisURLHostPortsList := strings.Split(redisURL, ",")
if len(redisURLHostPortsList) > 1 {
opt, err := redis.ParseURL(redisURLHostPortsList[0])
if err != nil {
log.Debug("error parsing redis url: ", err)
return err
}
urls := []string{opt.Addr}
urlList := redisURLHostPortsList[1:]
urls = append(urls, urlList...)
clusterOpt := &redis.ClusterOptions{Addrs: urls}
rdb := redis.NewClusterClient(clusterOpt)
ctx := context.Background()
_, err = rdb.Ping(ctx).Result()
if err != nil {
log.Debug("error connecting to redis: ", err)
return err
}
SessionStoreObj.RedisMemoryStoreObj = &RedisStore{
ctx: ctx,
store: rdb,
}
// return on successful initialization
return nil
}
opt, err := redis.ParseURL(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyRedisURL))
if err != nil {
log.Debug("error parsing redis url: ", err)
return err
}
rdb := redis.NewClient(opt)
ctx := context.Background()
_, err = rdb.Ping(ctx).Result()
if err != nil {
log.Debug("error connecting to redis: ", err)
return err
}
SessionStoreObj.RedisMemoryStoreObj = &RedisStore{
ctx: ctx,
store: rdb,
}
// return on successful initialization
return nil
}
log.Info("using in memory store to save sessions")
// if redis url is not set use in memory store
SessionStoreObj.InMemoryStoreObj = &InMemoryStore{
sessionStore: map[string]map[string]string{},
stateStore: map[string]string{},
}
return nil
}

View File

@ -8,8 +8,8 @@ import (
"github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/envstore"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/resolvers"
"github.com/authorizerdev/authorizer/server/sessionstore"
"github.com/stretchr/testify/assert"
)
@ -29,7 +29,7 @@ func logoutTests(t *testing.T, s TestSetup) {
})
token := *verifyRes.AccessToken
sessions := sessionstore.GetUserSessions(verifyRes.User.ID)
sessions := memorystore.Provider.GetUserSessions(verifyRes.User.ID)
cookie := ""
// set all they keys in cookie one of them should be session cookie
for key := range sessions {

View File

@ -9,8 +9,8 @@ import (
"github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/envstore"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/resolvers"
"github.com/authorizerdev/authorizer/server/sessionstore"
"github.com/stretchr/testify/assert"
)
@ -34,7 +34,7 @@ func sessionTests(t *testing.T, s TestSetup) {
Token: verificationRequest.Token,
})
sessions := sessionstore.GetUserSessions(verifyRes.User.ID)
sessions := memorystore.Provider.GetUserSessions(verifyRes.User.ID)
cookie := ""
token := *verifyRes.AccessToken
// set all they keys in cookie one of them should be session cookie

View File

@ -12,8 +12,8 @@ import (
"github.com/authorizerdev/authorizer/server/env"
"github.com/authorizerdev/authorizer/server/envstore"
"github.com/authorizerdev/authorizer/server/handlers"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/middlewares"
"github.com/authorizerdev/authorizer/server/sessionstore"
"github.com/gin-gonic/gin"
)
@ -77,16 +77,16 @@ func testSetup() TestSetup {
}
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyEnvPath, "../../.env.sample")
env.InitRequiredEnv()
memorystore.InitMemStore()
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeySmtpHost, "smtp.yopmail.com")
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeySmtpPort, "2525")
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeySmtpUsername, "lakhan@yopmail.com")
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeySmtpPassword, "test")
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeySenderEmail, "info@yopmail.com")
envstore.EnvStoreObj.UpdateEnvVariable(constants.SliceStoreIdentifier, constants.EnvKeyProtectedRoles, []string{"admin"})
memorystore.InitMemStore()
db.InitDB()
env.InitAllEnv()
sessionstore.InitSession()
w := httptest.NewRecorder()
c, r := gin.CreateTestContext(w)

View File

@ -6,8 +6,8 @@ import (
"github.com/authorizerdev/authorizer/server/db/models"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/resolvers"
"github.com/authorizerdev/authorizer/server/sessionstore"
"github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils"
"github.com/google/uuid"
@ -48,8 +48,8 @@ func validateJwtTokenTest(t *testing.T, s TestSetup) {
gc, err := utils.GinContextFromContext(ctx)
assert.NoError(t, err)
authToken, err := token.CreateAuthToken(gc, user, roles, scope)
sessionstore.SetState(authToken.AccessToken.Token, authToken.FingerPrint+"@"+user.ID)
sessionstore.SetState(authToken.RefreshToken.Token, authToken.FingerPrint+"@"+user.ID)
memorystore.Provider.SetState(authToken.AccessToken.Token, authToken.FingerPrint+"@"+user.ID)
memorystore.Provider.SetState(authToken.RefreshToken.Token, authToken.FingerPrint+"@"+user.ID)
t.Run(`should validate the access token`, func(t *testing.T) {
res, err := resolvers.ValidateJwtTokenResolver(ctx, model.ValidateJWTTokenInput{

View File

@ -17,7 +17,7 @@ import (
"github.com/authorizerdev/authorizer/server/crypto"
"github.com/authorizerdev/authorizer/server/db/models"
"github.com/authorizerdev/authorizer/server/envstore"
"github.com/authorizerdev/authorizer/server/sessionstore"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/utils"
)
@ -186,7 +186,7 @@ func ValidateAccessToken(gc *gin.Context, accessToken string) (map[string]interf
return res, fmt.Errorf(`unauthorized`)
}
savedSession := sessionstore.GetState(accessToken)
savedSession := memorystore.Provider.GetState(accessToken)
if savedSession == "" {
return res, fmt.Errorf(`unauthorized`)
}
@ -216,7 +216,7 @@ func ValidateRefreshToken(gc *gin.Context, refreshToken string) (map[string]inte
return res, fmt.Errorf(`unauthorized`)
}
savedSession := sessionstore.GetState(refreshToken)
savedSession := memorystore.Provider.GetState(refreshToken)
if savedSession == "" {
return res, fmt.Errorf(`unauthorized`)
}
@ -243,7 +243,7 @@ func ValidateBrowserSession(gc *gin.Context, encryptedSession string) (*SessionD
return nil, fmt.Errorf(`unauthorized`)
}
savedSession := sessionstore.GetState(encryptedSession)
savedSession := memorystore.Provider.GetState(encryptedSession)
if savedSession == "" {
return nil, fmt.Errorf(`unauthorized`)
}

12
server/utils/cli.go Normal file
View File

@ -0,0 +1,12 @@
package utils
var (
// ARG_DB_URL is the cli arg variable for the database url
ARG_DB_URL *string
// ARG_DB_TYPE is the cli arg variable for the database type
ARG_DB_TYPE *string
// ARG_ENV_FILE is the cli arg variable for the env file
ARG_ENV_FILE *string
// ARG_LOG_LEVEL is the cli arg variable for the log level
ARG_LOG_LEVEL *string
)