Files
maingate/core/platformgamepot.go

345 lines
9.7 KiB
Go

package core
import (
"bytes"
"encoding/json"
"errors"
"io"
"net/http"
"net/url"
"time"
"repositories.action2quare.com/ayo/gocommon/logger"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo/options"
)
type GamepotTemplate struct {
RedirectBaseUrl string
State string
}
type Gamepot_LoginValidationResponse struct {
Message string `json:"message"`
Status int `json:"status"`
}
func (mg *Maingate) platform_gamepot_get_login_url(w http.ResponseWriter, r *http.Request) {
browserinfo, err := mg.GetUserBrowserInfo(r)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
logger.Error(err)
return
}
existid := r.URL.Query().Get("existid")
withSDK := r.URL.Query().Get("withSDK")
//fmt.Println("existid =>", existid)
if existid != "" {
//기존 계정이 있는 경우에는 그 계정 부터 조회한다.
info, err := mg.getUserTokenWithCheck(AuthPlatformGamepot, existid, browserinfo)
if err == nil {
if info.token != "" {
params := url.Values{}
params.Add("id", existid)
params.Add("authtype", AuthPlatformGamepot)
if withSDK == "1" {
w.Write([]byte("?" + params.Encode()))
} else {
http.Redirect(w, r, "actionsquare://login?"+params.Encode(), http.StatusSeeOther)
}
return
}
}
}
sessionkey := mg.GeneratePlatformLoginNonceKey()
nonce := mg.GeneratePlatformLoginNonceKey()
mg.mongoClient.Delete(CollectionPlatformLoginToken, bson.M{
"platform": AuthPlatformGamepot,
"key": sessionkey,
})
_, _, err = mg.mongoClient.Update(CollectionPlatformLoginToken, bson.M{
"_id": primitive.NewObjectID(),
}, bson.M{
"$setOnInsert": bson.M{
"platform": AuthPlatformGamepot,
"key": sessionkey,
"nonce": nonce,
"brinfo": browserinfo,
},
}, options.Update().SetUpsert(true))
if err != nil {
w.WriteHeader(http.StatusBadRequest)
logger.Error(err)
return
}
// set cookie for storing token
cookie := http.Cookie{
Name: "LoginFlowContext_SessionKey",
Value: sessionkey,
Expires: time.Now().Add(1 * time.Hour),
//SameSite: http.SameSiteStrictMode,
SameSite: http.SameSiteLaxMode,
// HttpOnly: false,
Secure: true,
Path: "/",
}
http.SetCookie(w, &cookie)
if withSDK == "1" {
params := url.Values{}
params.Add("nonce", nonce)
w.Write([]byte("?" + params.Encode()))
} else {
var templateVar GamepotTemplate
templateVar.RedirectBaseUrl = mg.RedirectBaseUrl
templateVar.State = nonce
mg.webTemplate[AuthPlatformGamepot].Execute(w, templateVar)
}
}
func (mg *Maingate) platform_gamepot_authorize(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
brinfo, err := mg.GetUserBrowserInfo(r)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
logger.Error(err)
return
}
cookie, err := r.Cookie("LoginFlowContext_SessionKey")
if err != nil {
logger.Println("Session not found", err)
w.WriteHeader(http.StatusBadRequest)
return
}
r.ParseForm()
code := r.Form.Get("code")
state := r.Form.Get("state")
gamepotmemberId := r.Form.Get("id")
gamepotnickname := r.Form.Get("nickname")
gamepotprovider := r.Form.Get("provider")
gamepotproviderId := r.Form.Get("providerId")
// gamepotverify := r.Form.Get("verify")
// gamepotagree := r.Form.Get("agree")
bSuccess, Result := mg.platform_gamepot_authorize_raw(w, brinfo, code, state, cookie.Value, gamepotmemberId, gamepotnickname, gamepotprovider, gamepotproviderId)
if bSuccess {
http.Redirect(w, r, "actionsquare://login?"+Result, http.StatusSeeOther)
} else {
http.Redirect(w, r, "actionsquare://error", http.StatusSeeOther)
}
}
type GamePotSDKAuthInfo struct {
Code string `json:"code"`
State string `json:"state"`
MemberId string `json:"id"`
Nickname string `json:"nickname"`
Provider string `json:"provider"`
ProviderId string `json:"providerId"`
// Verify string `json:"verify"`
// Agree string `json:"agree"`
}
func (mg *Maingate) platform_gamepot_authorize_sdk(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
brinfo, err := mg.GetUserBrowserInfo(r)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
logger.Error(err)
return
}
cookie, err := r.Cookie("LoginFlowContext_SessionKey")
if err != nil {
logger.Println("Session not found", err)
w.WriteHeader(http.StatusBadRequest)
return
}
var authinfo GamePotSDKAuthInfo
err = json.NewDecoder(r.Body).Decode(&authinfo)
if err != nil {
logger.Println("authinfo decoding fail:", err)
w.WriteHeader(http.StatusBadRequest)
return
}
bSuccess, Result := mg.platform_gamepot_authorize_raw(w, brinfo, authinfo.Code, authinfo.State,
cookie.Value, authinfo.MemberId, authinfo.Nickname, authinfo.Provider, authinfo.ProviderId)
if bSuccess {
w.Write([]byte("?" + Result))
//http.Redirect(w, r, "actionsquare://login?"+Result, http.StatusSeeOther)
} else {
http.Redirect(w, r, "actionsquare://error", http.StatusSeeOther)
}
}
func (mg *Maingate) platform_gamepot_authorize_raw(w http.ResponseWriter, brinfo, code, state, cookieSessionKey, gamepotmemberId, gamepotnickname, gamepotprovider, gamepotproviderId string) (bool, string) {
found, err := mg.mongoClient.FindOne(CollectionPlatformLoginToken, bson.M{
"platform": AuthPlatformGamepot,
"key": cookieSessionKey,
})
if err != nil {
logger.Println("LoginFlowContext_SessionKey find key :", err)
w.WriteHeader(http.StatusBadRequest)
return false, ""
}
if found == nil {
logger.Println("LoginFlowContext_SessionKey not found")
w.WriteHeader(http.StatusBadRequest)
return false, ""
}
if cookieSessionKey != found["key"] {
logger.Println("LoginFlowContext_SessionKey key not match")
logger.Println(cookieSessionKey)
logger.Println(found["key"])
w.WriteHeader(http.StatusBadRequest)
return false, ""
}
if state != found["nonce"] {
logger.Println("LoginFlowContext_SessionKey nonce not match")
logger.Println(state)
logger.Println(found["nonce"])
w.WriteHeader(http.StatusBadRequest)
return false, ""
}
if brinfo != found["brinfo"] { //-- 로그인 시작점과 인증점의 브라우저 혹은 접속지 정보가 다르다?
logger.Println("LoginFlowContext_SessionKey brinfo not match ")
logger.Println(brinfo)
logger.Println(found["brinfo"])
w.WriteHeader(http.StatusBadRequest)
return false, ""
}
//=================
params := url.Values{}
params.Add("projectId", mg.GamepotProjectId)
params.Add("memberId", gamepotmemberId)
params.Add("token", code)
var respLoginCheck Gamepot_LoginValidationResponse
content := params.Encode()
resp, _ := http.Post(mg.GamepotLoginCheckAPIURL, "application/json", bytes.NewBuffer([]byte(content)))
if resp != nil {
body, _ := io.ReadAll(resp.Body)
json.Unmarshal(body, &respLoginCheck)
} else {
logger.Println("gamepot logincheck fail.")
w.WriteHeader(http.StatusBadRequest)
return false, ""
}
// fmt.Println("==============================")
// fmt.Println("respLoginCheck.Status:", respLoginCheck.Status)
// fmt.Println("respLoginCheck.Message:", respLoginCheck.Message)
// fmt.Println("==============================")
if respLoginCheck.Status != 0 {
logger.Errorf("gamepot login fail:", respLoginCheck.Message)
w.WriteHeader(http.StatusBadRequest)
return false, ""
}
acceestoken_expire_time := time.Date(2999, 1, int(time.January), 0, 0, 0, 0, time.UTC).Unix()
if gamepotmemberId != "" && gamepotprovider != "" && gamepotproviderId != "" {
var info usertokeninfo
info.platform = AuthPlatformGamepot
info.userid = gamepotmemberId
//== memberid 제외하고는 모두 client로 부터 온 값이기 때문에 유효성이 확인된 값이 아니다. 하지만, 참조용으로 사용은 한다.
// 정확한 정보는 gamepotid를 gamepot dashboard에서 조회해서 확인 할 수 밖에 없다.
info.token = gamepotprovider + "-" + gamepotproviderId
info.brinfo = brinfo
info.accesstoken = ""
info.accesstoken_expire_time = acceestoken_expire_time
mg.setUserToken(info)
mg.mongoClient.Delete(CollectionGamepotUserInfo, bson.M{
"gamepotuserid": info.userid,
})
_, _, err := mg.mongoClient.Update(CollectionGamepotUserInfo, bson.M{
"_id": primitive.NewObjectID(),
}, bson.M{
"$setOnInsert": bson.M{
"gamepotuserid": gamepotmemberId,
"gamepotnickname": gamepotnickname,
"gamepotprovider": gamepotprovider,
"gamepotproviderId": gamepotproviderId,
// "gamepotverify": gamepotverify,
// "gamepotagree": gamepotagree,
"updatetime": time.Now(),
},
}, options.Update().SetUpsert(true))
if err != nil {
logger.Error(err)
}
params := url.Values{}
params.Add("id", gamepotmemberId)
params.Add("authtype", AuthPlatformGamepot)
return true, params.Encode()
}
return false, ""
}
func (mg *Maingate) platform_gamepot_getuserinfo(info usertokeninfo) (bool, string, string) {
found, err := mg.mongoClient.FindOne(CollectionGamepotUserInfo, bson.M{
"gamepotuserid": info.userid,
})
if err != nil {
logger.Error(err)
return false, "", ""
}
if found == nil {
logger.Error(errors.New("gamepot info not found: " + info.userid))
return false, "", ""
}
gamepotprovider := found["gamepotprovider"].(string)
gamepotproviderId := found["gamepotproviderId"].(string)
if gamepotprovider+"-"+gamepotproviderId != info.token {
logger.Println("gamepot info not match..") //-- token은 플랫폼종류+플랫폼ID로 구성했는데... 검증할 방법이 없어서 client로 부터 온값을 쓴다. 그래도 유저가 조작하지 않는 이상 일치해야 된다.
logger.Println(info.token)
logger.Println(gamepotprovider + "-" + gamepotproviderId)
return false, "", ""
}
tempEmail := info.userid + "@gamepot" //-- 게임팟은 email을 안줘서 일단 gamepotid기준으로 임시값을 할당한다.
return true, info.userid, tempEmail
}