From b69d0b8e23f79e5f2b2b3103698cb26aec5810b8 Mon Sep 17 00:00:00 2001 From: Lakhan Samani Date: Wed, 27 Oct 2021 23:15:38 +0530 Subject: [PATCH] Feat/multiple session (#64) * fix: disable windows build * feat: add ability to handle multiple sessions --- .github/workflows/release.yaml | 13 +++--- TODO.md | 6 +++ server/db/db.go | 3 +- server/db/session.go | 39 ++++++++++++++++ server/db/verificationRequests.go | 1 + server/handlers/oauthCallback.go | 15 ++++-- server/handlers/oauthLogin.go | 6 +-- server/handlers/verifyEmail.go | 11 ++++- server/resolvers/adminUpdateUser.go | 4 +- server/resolvers/deleteUser.go | 2 +- server/resolvers/login.go | 11 ++++- server/resolvers/logout.go | 2 +- server/resolvers/profile.go | 2 +- server/resolvers/signup.go | 11 ++++- server/resolvers/token.go | 14 +++++- server/resolvers/updateProfile.go | 4 +- server/resolvers/verifyEmail.go | 11 ++++- server/session/inMemoryStore.go | 71 ++++++++++++++++++++++++----- server/session/redisStore.go | 47 +++++++++++++++++-- server/session/session.go | 62 +++++++++++++++++++++---- server/utils/requestInfo.go | 19 ++++++++ 21 files changed, 301 insertions(+), 53 deletions(-) create mode 100644 server/db/session.go create mode 100644 server/utils/requestInfo.go diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 6250bfb..48a9dea 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -36,12 +36,12 @@ jobs: run: echo VERSION=$(basename ${GITHUB_REF}) >> ${GITHUB_ENV} - name: Copy .env file run: mv .env.sample .env - - name: Package files for windows - run: | - make clean && \ - CGO_ENABLED=1 GOOS=windows CC=/usr/bin/x86_64-w64-mingw32-gcc make && \ - mv build/server build/server.exe && \ - zip -vr authorizer-${VERSION}-windows-amd64.zip .env app/build build templates + # - name: Package files for windows + # run: | + # make clean && \ + # CGO_ENABLED=1 GOOS=windows CC=/usr/bin/x86_64-w64-mingw32-gcc make && \ + # mv build/server build/server.exe && \ + # zip -vr authorizer-${VERSION}-windows-amd64.zip .env app/build build templates - name: Package files for linux run: | make clean && \ @@ -49,7 +49,6 @@ jobs: tar cvfz authorizer-${VERSION}-linux-amd64.tar.gz .env app/build build templates - name: Upload assets run: | - github-assets-uploader -f authorizer-${VERSION}-windows-amd64.zip -mediatype application/zip -repo authorizerdev/authorizer -token ${{secrets.RELEASE_TOKEN}} -tag ${VERSION} && \ github-assets-uploader -f authorizer-${VERSION}-linux-amd64.tar.gz -mediatype application/gzip -repo authorizerdev/authorizer -token ${{secrets.RELEASE_TOKEN}} -tag ${VERSION} - name: Log in to Docker Hub uses: docker/login-action@v1 diff --git a/TODO.md b/TODO.md index 0a262bf..6870f7f 100644 --- a/TODO.md +++ b/TODO.md @@ -1,5 +1,11 @@ # Task List +## Feature Multiple sessions + +- Multiple sessions for users to login use hMset from redis for this + user_id access_token1 long_live_token1 + user_id access_token2 long_live_token2 + # Feature roles For the first version we will only support setting roles master list via env diff --git a/server/db/db.go b/server/db/db.go index 79a5af2..e856d1d 100644 --- a/server/db/db.go +++ b/server/db/db.go @@ -27,6 +27,7 @@ type Manager interface { GetVerificationByEmail(email string) (VerificationRequest, error) DeleteUser(email string) error SaveRoles(roles []Role) error + SaveSession(session Session) error } type manager struct { @@ -56,7 +57,7 @@ func InitDB() { if err != nil { log.Fatal("Failed to init db:", err) } else { - db.AutoMigrate(&User{}, &VerificationRequest{}, &Role{}) + db.AutoMigrate(&User{}, &VerificationRequest{}, &Role{}, &Session{}) } Mgr = &manager{db: db} diff --git a/server/db/session.go b/server/db/session.go new file mode 100644 index 0000000..625fdf1 --- /dev/null +++ b/server/db/session.go @@ -0,0 +1,39 @@ +package db + +import ( + "log" + + "github.com/google/uuid" + "gorm.io/gorm" + "gorm.io/gorm/clause" +) + +type Session struct { + ID uuid.UUID `gorm:"type:uuid;"` + UserID uuid.UUID `gorm:"type:uuid;"` + User User + UserAgent string + IP string + CreatedAt int64 `gorm:"autoCreateTime"` + UpdatedAt int64 `gorm:"autoUpdateTime"` +} + +func (r *Session) BeforeCreate(tx *gorm.DB) (err error) { + r.ID = uuid.New() + + return +} + +// SaveSession function to save user sessiosn +func (mgr *manager) SaveSession(session Session) error { + res := mgr.db.Clauses( + clause.OnConflict{ + DoNothing: true, + }).Create(&session) + if res.Error != nil { + log.Println(`Error saving session`, res.Error) + return res.Error + } + + return nil +} diff --git a/server/db/verificationRequests.go b/server/db/verificationRequests.go index 18a4ba1..f74b5ba 100644 --- a/server/db/verificationRequests.go +++ b/server/db/verificationRequests.go @@ -30,6 +30,7 @@ func (mgr *manager) AddVerification(verification VerificationRequest) (Verificat Columns: []clause.Column{{Name: "email"}}, DoUpdates: clause.AssignmentColumns([]string{"token", "identifier", "expires_at"}), }).Create(&verification) + if result.Error != nil { log.Println(`Error saving verification record`, result.Error) return verification, result.Error diff --git a/server/handlers/oauthCallback.go b/server/handlers/oauthCallback.go index b920d8a..948bdbf 100644 --- a/server/handlers/oauthCallback.go +++ b/server/handlers/oauthCallback.go @@ -147,11 +147,11 @@ func OAuthCallbackHandler() gin.HandlerFunc { provider := c.Param("oauth_provider") state := c.Request.FormValue("state") - sessionState := session.GetToken(state) + sessionState := session.GetSocailLoginState(state) if sessionState == "" { c.JSON(400, gin.H{"error": "invalid oauth state"}) } - session.DeleteToken(sessionState) + session.RemoveSocialLoginState(state) // contains random token, redirect url, role sessionSplit := strings.Split(state, "___") @@ -254,7 +254,16 @@ func OAuthCallbackHandler() gin.HandlerFunc { accessToken, _, _ := utils.CreateAuthToken(user, enum.AccessToken, inputRoles) utils.SetCookie(c, accessToken) - session.SetToken(userIdStr, refreshToken) + session.SetToken(userIdStr, accessToken, refreshToken) + go func() { + sessionData := db.Session{ + UserID: user.ID, + UserAgent: utils.GetUserAgent(c.Request), + IP: utils.GetIP(c.Request), + } + + db.Mgr.SaveSession(sessionData) + }() c.Redirect(http.StatusTemporaryRedirect, redirectURL) } diff --git a/server/handlers/oauthLogin.go b/server/handlers/oauthLogin.go index 31aca8e..9f50d9f 100644 --- a/server/handlers/oauthLogin.go +++ b/server/handlers/oauthLogin.go @@ -51,18 +51,18 @@ func OAuthLoginHandler() gin.HandlerFunc { switch provider { case enum.Google.String(): - session.SetToken(oauthStateString, enum.Google.String()) + session.SetSocailLoginState(oauthStateString, enum.Google.String()) // during the init of OAuthProvider authorizer url might be empty oauth.OAuthProvider.GoogleConfig.RedirectURL = constants.AUTHORIZER_URL + "/oauth_callback/google" url := oauth.OAuthProvider.GoogleConfig.AuthCodeURL(oauthStateString) c.Redirect(http.StatusTemporaryRedirect, url) case enum.Github.String(): - session.SetToken(oauthStateString, enum.Github.String()) + session.SetSocailLoginState(oauthStateString, enum.Github.String()) oauth.OAuthProvider.GithubConfig.RedirectURL = constants.AUTHORIZER_URL + "/oauth_callback/github" url := oauth.OAuthProvider.GithubConfig.AuthCodeURL(oauthStateString) c.Redirect(http.StatusTemporaryRedirect, url) case enum.Facebook.String(): - session.SetToken(oauthStateString, enum.Github.String()) + session.SetSocailLoginState(oauthStateString, enum.Facebook.String()) oauth.OAuthProvider.FacebookConfig.RedirectURL = constants.AUTHORIZER_URL + "/oauth_callback/facebook" url := oauth.OAuthProvider.FacebookConfig.AuthCodeURL(oauthStateString) c.Redirect(http.StatusTemporaryRedirect, url) diff --git a/server/handlers/verifyEmail.go b/server/handlers/verifyEmail.go index 2e768ca..0e1f9d9 100644 --- a/server/handlers/verifyEmail.go +++ b/server/handlers/verifyEmail.go @@ -56,7 +56,16 @@ func VerifyEmailHandler() gin.HandlerFunc { accessToken, _, _ := utils.CreateAuthToken(user, enum.AccessToken, roles) - session.SetToken(userIdStr, refreshToken) + session.SetToken(userIdStr, accessToken, refreshToken) + go func() { + sessionData := db.Session{ + UserID: user.ID, + UserAgent: utils.GetUserAgent(c.Request), + IP: utils.GetIP(c.Request), + } + + db.Mgr.SaveSession(sessionData) + }() utils.SetCookie(c, accessToken) c.Redirect(http.StatusTemporaryRedirect, claim.Host) } diff --git a/server/resolvers/adminUpdateUser.go b/server/resolvers/adminUpdateUser.go index 334c4a9..45d9733 100644 --- a/server/resolvers/adminUpdateUser.go +++ b/server/resolvers/adminUpdateUser.go @@ -60,7 +60,7 @@ func AdminUpdateUser(ctx context.Context, params model.AdminUpdateUserInput) (*m return res, fmt.Errorf("user with this email address already exists") } - session.DeleteToken(fmt.Sprintf("%v", user.ID)) + session.DeleteUserSession(fmt.Sprintf("%v", user.ID)) utils.DeleteCookie(gc) user.Email = newEmail @@ -100,7 +100,7 @@ func AdminUpdateUser(ctx context.Context, params model.AdminUpdateUserInput) (*m rolesToSave = strings.Join(inputRoles, ",") } - session.DeleteToken(fmt.Sprintf("%v", user.ID)) + session.DeleteUserSession(fmt.Sprintf("%v", user.ID)) utils.DeleteCookie(gc) } diff --git a/server/resolvers/deleteUser.go b/server/resolvers/deleteUser.go index 2631152..31bb6cd 100644 --- a/server/resolvers/deleteUser.go +++ b/server/resolvers/deleteUser.go @@ -27,7 +27,7 @@ func DeleteUser(ctx context.Context, params model.DeleteUserInput) (*model.Respo return res, err } - session.DeleteToken(fmt.Sprintf("%x", user.ID)) + session.DeleteUserSession(fmt.Sprintf("%x", user.ID)) err = db.Mgr.DeleteUser(params.Email) if err != nil { diff --git a/server/resolvers/login.go b/server/resolvers/login.go index b112f3f..5fb4f39 100644 --- a/server/resolvers/login.go +++ b/server/resolvers/login.go @@ -60,7 +60,16 @@ func Login(ctx context.Context, params model.LoginInput) (*model.AuthResponse, e accessToken, expiresAt, _ := utils.CreateAuthToken(user, enum.AccessToken, roles) - session.SetToken(userIdStr, refreshToken) + session.SetToken(userIdStr, accessToken, refreshToken) + go func() { + sessionData := db.Session{ + UserID: user.ID, + UserAgent: utils.GetUserAgent(gc.Request), + IP: utils.GetIP(gc.Request), + } + + db.Mgr.SaveSession(sessionData) + }() res = &model.AuthResponse{ Message: `Logged in successfully`, diff --git a/server/resolvers/logout.go b/server/resolvers/logout.go index 7d623c2..2a1633a 100644 --- a/server/resolvers/logout.go +++ b/server/resolvers/logout.go @@ -27,7 +27,7 @@ func Logout(ctx context.Context) (*model.Response, error) { } userId := fmt.Sprintf("%v", claim["id"]) - session.DeleteToken(userId) + session.DeleteToken(userId, token) res = &model.Response{ Message: "Logged out successfully", } diff --git a/server/resolvers/profile.go b/server/resolvers/profile.go index 3c21676..f11b1fb 100644 --- a/server/resolvers/profile.go +++ b/server/resolvers/profile.go @@ -30,7 +30,7 @@ func Profile(ctx context.Context) (*model.User, error) { userID := fmt.Sprintf("%v", claim["id"]) email := fmt.Sprintf("%v", claim["email"]) - sessionToken := session.GetToken(userID) + sessionToken := session.GetToken(userID, token) if sessionToken == "" { return res, fmt.Errorf(`unauthorized`) diff --git a/server/resolvers/signup.go b/server/resolvers/signup.go index 8cebd10..6ee7393 100644 --- a/server/resolvers/signup.go +++ b/server/resolvers/signup.go @@ -127,7 +127,16 @@ func Signup(ctx context.Context, params model.SignUpInput) (*model.AuthResponse, accessToken, expiresAt, _ := utils.CreateAuthToken(user, enum.AccessToken, roles) - session.SetToken(userIdStr, refreshToken) + session.SetToken(userIdStr, accessToken, refreshToken) + go func() { + sessionData := db.Session{ + UserID: user.ID, + UserAgent: utils.GetUserAgent(gc.Request), + IP: utils.GetIP(gc.Request), + } + + db.Mgr.SaveSession(sessionData) + }() res = &model.AuthResponse{ Message: `Signed up successfully.`, AccessToken: &accessToken, diff --git a/server/resolvers/token.go b/server/resolvers/token.go index b00bf12..1c4d674 100644 --- a/server/resolvers/token.go +++ b/server/resolvers/token.go @@ -37,7 +37,7 @@ func Token(ctx context.Context, roles []string) (*model.AuthResponse, error) { userIdStr := fmt.Sprintf("%v", user.ID) - sessionToken := session.GetToken(userIdStr) + sessionToken := session.GetToken(userIdStr, token) if sessionToken == "" { return res, fmt.Errorf(`unauthorized`) @@ -63,7 +63,19 @@ func Token(ctx context.Context, roles []string) (*model.AuthResponse, error) { if accessTokenErr != nil || expiresTimeObj.Sub(currentTimeObj).Minutes() <= 5 { // if access token has expired and refresh/session token is valid // generate new accessToken + currentRefreshToken := session.GetToken(userIdStr, token) + session.DeleteToken(userIdStr, token) token, expiresAt, _ = utils.CreateAuthToken(user, enum.AccessToken, claimRoles) + session.SetToken(userIdStr, token, currentRefreshToken) + go func() { + sessionData := db.Session{ + UserID: user.ID, + UserAgent: utils.GetUserAgent(gc.Request), + IP: utils.GetIP(gc.Request), + } + + db.Mgr.SaveSession(sessionData) + }() } utils.SetCookie(gc, token) diff --git a/server/resolvers/updateProfile.go b/server/resolvers/updateProfile.go index 14d47ec..5816910 100644 --- a/server/resolvers/updateProfile.go +++ b/server/resolvers/updateProfile.go @@ -33,7 +33,7 @@ func UpdateProfile(ctx context.Context, params model.UpdateProfileInput) (*model } id := fmt.Sprintf("%v", claim["id"]) - sessionToken := session.GetToken(id) + sessionToken := session.GetToken(id, token) if sessionToken == "" { return res, fmt.Errorf(`unauthorized`) @@ -99,7 +99,7 @@ func UpdateProfile(ctx context.Context, params model.UpdateProfileInput) (*model return res, fmt.Errorf("user with this email address already exists") } - session.DeleteToken(fmt.Sprintf("%v", user.ID)) + session.DeleteUserSession(fmt.Sprintf("%v", user.ID)) utils.DeleteCookie(gc) user.Email = newEmail diff --git a/server/resolvers/verifyEmail.go b/server/resolvers/verifyEmail.go index 92bccd8..a1f90e3 100644 --- a/server/resolvers/verifyEmail.go +++ b/server/resolvers/verifyEmail.go @@ -47,7 +47,16 @@ func VerifyEmail(ctx context.Context, params model.VerifyEmailInput) (*model.Aut accessToken, expiresAt, _ := utils.CreateAuthToken(user, enum.AccessToken, roles) - session.SetToken(userIdStr, refreshToken) + session.SetToken(userIdStr, accessToken, refreshToken) + go func() { + sessionData := db.Session{ + UserID: user.ID, + UserAgent: utils.GetUserAgent(gc.Request), + IP: utils.GetIP(gc.Request), + } + + db.Mgr.SaveSession(sessionData) + }() res = &model.AuthResponse{ Message: `Email verified successfully.`, diff --git a/server/session/inMemoryStore.go b/server/session/inMemoryStore.go index ee76e46..164b7d0 100644 --- a/server/session/inMemoryStore.go +++ b/server/session/inMemoryStore.go @@ -1,41 +1,88 @@ package session -import "sync" +import ( + "log" + "sync" +) type InMemoryStore struct { - mu sync.Mutex - store map[string]string + mu sync.Mutex + store map[string]map[string]string + socialLoginState map[string]string } -func (c *InMemoryStore) AddToken(userId, token string) { +func (c *InMemoryStore) AddToken(userId, accessToken, refreshToken string) { c.mu.Lock() // delete sessions > 500 // not recommended for production if len(c.store) >= 500 { - c.store = make(map[string]string) + c.store = map[string]map[string]string{} } - c.store[userId] = token + // check if entry exists in map + _, exists := c.store[userId] + if exists { + tempMap := c.store[userId] + tempMap[accessToken] = refreshToken + c.store[userId] = tempMap + } else { + tempMap := map[string]string{ + accessToken: refreshToken, + } + c.store[userId] = tempMap + } + + log.Println(c.store) + c.mu.Unlock() } -func (c *InMemoryStore) DeleteToken(userId string) { +func (c *InMemoryStore) DeleteUserSession(userId string) { c.mu.Lock() delete(c.store, userId) c.mu.Unlock() } -func (c *InMemoryStore) ClearStore() { +func (c *InMemoryStore) DeleteToken(userId, accessToken string) { c.mu.Lock() - c.store = make(map[string]string) + delete(c.store[userId], accessToken) c.mu.Unlock() } -func (c *InMemoryStore) GetToken(userId string) string { +func (c *InMemoryStore) ClearStore() { + c.mu.Lock() + c.store = map[string]map[string]string{} + c.mu.Unlock() +} + +func (c *InMemoryStore) GetToken(userId, accessToken string) string { token := "" c.mu.Lock() - if val, ok := c.store[userId]; ok { - token = val + if sessionMap, ok := c.store[userId]; ok { + if val, ok := sessionMap[accessToken]; ok { + token = val + } } c.mu.Unlock() return token } + +func (c *InMemoryStore) SetSocialLoginState(key, state string) { + c.mu.Lock() + c.socialLoginState[key] = state + c.mu.Unlock() +} + +func (c *InMemoryStore) GetSocialLoginState(key string) string { + state := "" + if stateVal, ok := c.socialLoginState[key]; ok { + state = stateVal + } + + return state +} + +func (c *InMemoryStore) RemoveSocialLoginState(key string) { + c.mu.Lock() + delete(c.socialLoginState, key) + c.mu.Unlock() +} diff --git a/server/session/redisStore.go b/server/session/redisStore.go index b21b0b2..91cb5ed 100644 --- a/server/session/redisStore.go +++ b/server/session/redisStore.go @@ -2,6 +2,7 @@ package session import ( "context" + "fmt" "log" "github.com/go-redis/redis/v8" @@ -12,20 +13,29 @@ type RedisStore struct { store *redis.Client } -func (c *RedisStore) AddToken(userId, token string) { - err := c.store.Set(c.ctx, "authorizer_"+userId, token, 0).Err() +func (c *RedisStore) AddToken(userId, accessToken, refreshToken string) { + err := c.store.HMSet(c.ctx, "authorizer_"+userId, map[string]string{ + accessToken: refreshToken, + }).Err() if err != nil { log.Fatalln("Error saving redis token:", err) } } -func (c *RedisStore) DeleteToken(userId string) { +func (c *RedisStore) DeleteUserSession(userId string) { err := c.store.Del(c.ctx, "authorizer_"+userId).Err() if err != nil { log.Fatalln("Error deleting redis token:", err) } } +func (c *RedisStore) DeleteToken(userId, accessToken string) { + err := c.store.HDel(c.ctx, "authorizer_"+userId, accessToken).Err() + if err != nil { + log.Fatalln("Error deleting redis token:", err) + } +} + func (c *RedisStore) ClearStore() { err := c.store.Del(c.ctx, "authorizer_*").Err() if err != nil { @@ -33,11 +43,38 @@ func (c *RedisStore) ClearStore() { } } -func (c *RedisStore) GetToken(userId string) string { +func (c *RedisStore) GetToken(userId, accessToken string) string { token := "" - token, err := c.store.Get(c.ctx, "authorizer_"+userId).Result() + res, err := c.store.HMGet(c.ctx, "authorizer_"+userId, accessToken).Result() if err != nil { log.Println("Error getting token from redis store:", err) } + if len(res) > 0 && res[0] != nil { + token = fmt.Sprintf("%v", res[0]) + } return token } + +func (c *RedisStore) SetSocialLoginState(key, state string) { + err := c.store.Set(c.ctx, key, state, 0).Err() + if err != nil { + log.Fatalln("Error saving redis token:", err) + } +} + +func (c *RedisStore) GetSocialLoginState(key string) string { + state := "" + state, err := c.store.Get(c.ctx, key).Result() + if err != nil { + log.Println("Error getting token from redis store:", err) + } + + return state +} + +func (c *RedisStore) RemoveSocialLoginState(key string) { + err := c.store.Del(c.ctx, key).Err() + if err != nil { + log.Fatalln("Error deleting redis token:", err) + } +} diff --git a/server/session/session.go b/server/session/session.go index 1567ed3..15d4015 100644 --- a/server/session/session.go +++ b/server/session/session.go @@ -15,30 +15,42 @@ type SessionStore struct { var SessionStoreObj SessionStore -func SetToken(userId, token string) { +func SetToken(userId, accessToken, refreshToken string) { + // TODO: Set session information in db for all the sessions that gets generated + // it should async go function + if SessionStoreObj.RedisMemoryStoreObj != nil { - SessionStoreObj.RedisMemoryStoreObj.AddToken(userId, token) + SessionStoreObj.RedisMemoryStoreObj.AddToken(userId, accessToken, refreshToken) } if SessionStoreObj.InMemoryStoreObj != nil { - SessionStoreObj.InMemoryStoreObj.AddToken(userId, token) + SessionStoreObj.InMemoryStoreObj.AddToken(userId, accessToken, refreshToken) } } -func DeleteToken(userId string) { +func DeleteToken(userId, accessToken string) { if SessionStoreObj.RedisMemoryStoreObj != nil { - SessionStoreObj.RedisMemoryStoreObj.DeleteToken(userId) + SessionStoreObj.RedisMemoryStoreObj.DeleteToken(userId, accessToken) } if SessionStoreObj.InMemoryStoreObj != nil { - SessionStoreObj.InMemoryStoreObj.DeleteToken(userId) + SessionStoreObj.InMemoryStoreObj.DeleteToken(userId, accessToken) } } -func GetToken(userId string) string { +func DeleteUserSession(userId string) { if SessionStoreObj.RedisMemoryStoreObj != nil { - return SessionStoreObj.RedisMemoryStoreObj.GetToken(userId) + SessionStoreObj.RedisMemoryStoreObj.DeleteUserSession(userId) } if SessionStoreObj.InMemoryStoreObj != nil { - return SessionStoreObj.InMemoryStoreObj.GetToken(userId) + SessionStoreObj.InMemoryStoreObj.DeleteUserSession(userId) + } +} + +func GetToken(userId, accessToken string) string { + if SessionStoreObj.RedisMemoryStoreObj != nil { + return SessionStoreObj.RedisMemoryStoreObj.GetToken(userId, accessToken) + } + if SessionStoreObj.InMemoryStoreObj != nil { + return SessionStoreObj.InMemoryStoreObj.GetToken(userId, accessToken) } return "" @@ -53,6 +65,35 @@ func ClearStore() { } } +func SetSocailLoginState(key, state string) { + if SessionStoreObj.RedisMemoryStoreObj != nil { + SessionStoreObj.RedisMemoryStoreObj.SetSocialLoginState(key, state) + } + if SessionStoreObj.InMemoryStoreObj != nil { + SessionStoreObj.InMemoryStoreObj.SetSocialLoginState(key, state) + } +} + +func GetSocailLoginState(key string) string { + if SessionStoreObj.RedisMemoryStoreObj != nil { + return SessionStoreObj.RedisMemoryStoreObj.GetSocialLoginState(key) + } + if SessionStoreObj.InMemoryStoreObj != nil { + return SessionStoreObj.InMemoryStoreObj.GetSocialLoginState(key) + } + + return "" +} + +func RemoveSocialLoginState(key string) { + if SessionStoreObj.RedisMemoryStoreObj != nil { + SessionStoreObj.RedisMemoryStoreObj.RemoveSocialLoginState(key) + } + if SessionStoreObj.InMemoryStoreObj != nil { + SessionStoreObj.InMemoryStoreObj.RemoveSocialLoginState(key) + } +} + func InitSession() { if constants.REDIS_URL != "" { log.Println("Using redis store to save sessions") @@ -75,7 +116,8 @@ func InitSession() { } else { log.Println("Using in memory store to save sessions") SessionStoreObj.InMemoryStoreObj = &InMemoryStore{ - store: make(map[string]string), + store: map[string]map[string]string{}, + socialLoginState: map[string]string{}, } } } diff --git a/server/utils/requestInfo.go b/server/utils/requestInfo.go new file mode 100644 index 0000000..226078e --- /dev/null +++ b/server/utils/requestInfo.go @@ -0,0 +1,19 @@ +package utils + +import "net/http" + +func GetIP(r *http.Request) string { + IPAddress := r.Header.Get("X-Real-Ip") + if IPAddress == "" { + IPAddress = r.Header.Get("X-Forwarded-For") + } + + if IPAddress == "" { + IPAddress = r.RemoteAddr + } + return IPAddress +} + +func GetUserAgent(r *http.Request) string { + return r.UserAgent() +}