diff --git a/core/maingate.go b/core/maingate.go index f92977a..932189d 100644 --- a/core/maingate.go +++ b/core/maingate.go @@ -51,6 +51,7 @@ var ( ) const ( + AuthPlatformSteamSDK = "steam" AuthPlatformFirebaseAuth = "firebase" AuthPlatformGoogle = "google" AuthPlatformMicrosoft = "microsoft" @@ -139,6 +140,8 @@ type maingateConfig struct { GamepotProjectId string `json:"gamepot_project_id"` GamepotLoginCheckAPIURL string `json:"gamepot_logincheckapi_url"` FirebaseAdminSDKCredentialFile string `json:"firebase_admin_sdk_credentialfile"` + SteamAppId string `json:"steam_app_id"` + SteamPublisherAuthKey string `json:"steam_publisher_authkey"` } type globalAdmins struct { @@ -571,6 +574,8 @@ func (mg *Maingate) RegisterHandlers(ctx context.Context, serveMux *http.ServeMu serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "request_login_url", AuthPlatformFirebaseAuth), mg.platform_firebaseauth_get_login_url) serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "authorize_sdk", AuthPlatformFirebaseAuth), mg.platform_firebaseauth_authorize_sdk) + serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "authorize_sdk", AuthPlatformSteamSDK), mg.platform_steamsdk_authorize) + go mg.watchServiceCollection(ctx, serveMux, prefix) go mg.watchFileCollection(ctx, serveMux, prefix) // fsx := http.FileServer(http.Dir("console")) @@ -740,6 +745,8 @@ func (mg *Maingate) updateUserinfo(info usertokeninfo) (bool, string, string) { success, userid, email = mg.platform_microsoft_getuserinfo(info) case AuthPlatformGoogle: success, userid, email = mg.platform_google_getuserinfo(info) + case AuthPlatformSteamSDK: + success, userid, email = mg.platform_steamsdk_getuserinfo(info) case AuthPlatformFirebaseAuth: success, userid, email = mg.platform_firebase_getuserinfo(info) } diff --git a/core/platformsteam.go b/core/platformsteam.go new file mode 100644 index 0000000..b52f25e --- /dev/null +++ b/core/platformsteam.go @@ -0,0 +1,125 @@ +package core + +import ( + "encoding/json" + "errors" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/url" + "strings" + "time" + + "repositories.action2quare.com/ayo/gocommon/logger" +) + +type SteamSDKAuthInfo struct { + UserSteamId string `json:"steamid"` + UserAuthToken string `json:"authtoken"` +} + +func (mg *Maingate) platform_steamsdk_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 + } + + var authinfo SteamSDKAuthInfo + + err = json.NewDecoder(r.Body).Decode(&authinfo) + if err != nil { + logger.Println("authinfo decoding fail:", err) + w.WriteHeader(http.StatusBadRequest) + return + } + + err = authenticateSteamUser(mg.SteamPublisherAuthKey, mg.SteamAppId, authinfo.UserSteamId, authinfo.UserAuthToken) + + if err == nil { + + acceestoken_expire_time := time.Date(2999, 1, int(time.January), 0, 0, 0, 0, time.UTC).Unix() + + var info usertokeninfo + info.platform = AuthPlatformSteamSDK + info.userid = authinfo.UserSteamId + info.token = authinfo.UserAuthToken + info.brinfo = brinfo + //info.accesstoken = respReferesh.AccessToken + info.accesstoken_expire_time = acceestoken_expire_time + mg.setUserToken(info) + + params := url.Values{} + params.Add("id", authinfo.UserSteamId) + params.Add("authtype", AuthPlatformSteamSDK) + w.Write([]byte("?" + params.Encode())) + //http.Redirect(w, r, "actionsquare://login?"+Result, http.StatusSeeOther) + } else { + logger.Println(err) + http.Redirect(w, r, "actionsquare://error", http.StatusSeeOther) + } + +} + +func authenticateSteamUser(pubkey, appid, playerid, ticket string) error { + // Returns: The user's 64-bit SteamID if the user's ticket is valid + url := fmt.Sprintf("https://partner.steam-api.com/ISteamUserAuth/AuthenticateUserTicket/v1/?key=%s&appid=%s&ticket=%s", pubkey, appid, ticket) + resp, e := http.Get(url) + if e != nil { + return e + } + defer func() { + io.Copy(io.Discard, resp.Body) + resp.Body.Close() + }() + + body, e := ioutil.ReadAll(resp.Body) + if e != nil { + return e + } + + // fmt.Println(url) + // fmt.Println(string(body)) + + var doc map[string]interface{} + if err := json.Unmarshal(body, &doc); err != nil { + return err + } + + if v, ok := doc["response"]; ok { + response := v.(map[string]interface{}) + if v, ok = response["params"]; ok { + paramsnode := v.(map[string]interface{}) + if v, ok = paramsnode["result"]; ok { + if v.(string) == "OK" { + if v, ok = paramsnode["steamid"]; ok { + // playerid에는 빌드 구성 suffix가 붙어있는 상태이므로 == 비교가 아니라 HasPrefix로 비교 + if strings.HasPrefix(playerid, v.(string)) { + return nil + } + } + } else if v.(string) == "Invalid ticket" { + return errors.New("steam: invalid ticket") + } + } + } else if errdocraw, ok := response["error"]; ok { + errdoc := errdocraw.(map[string]interface{}) + desc := errdoc["errordesc"].(string) + return errors.New(desc) + } + } + return errors.New("steam: response is not expected") +} + +func (mg *Maingate) platform_steamsdk_getuserinfo(info usertokeninfo) (bool, string, string) { + + // Steam은 이메일 정보를 받을수 없기 때문에 dummy임시 주소 할당하여 리턴한다. + dummyEmail := fmt.Sprintf("__dummy_%s@steamtemp__", info.userid) + return true, info.userid, dummyEmail + +} diff --git a/go.sum b/go.sum index ed441d2..26cff37 100644 --- a/go.sum +++ b/go.sum @@ -268,5 +268,27 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230612013915-5950ff4bb82e h1:m0jo1r+2NtBfxwj92e6EVaBZpzTDT6Hq7D93vWO4h9Y= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230612013915-5950ff4bb82e/go.mod h1:ng62uGMGXyQSeuxePG5gJAMtip4Rnspu5Tu7hgvaXns= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230614091557-9b877d9a732c h1:fhCuu0jFps8T1sN8hO0fGnatvNDW6VwM96PV26EA3T4= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230614091557-9b877d9a732c/go.mod h1:ng62uGMGXyQSeuxePG5gJAMtip4Rnspu5Tu7hgvaXns= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230616031450-0b2c9351a717 h1:WrkkEWN3bh1QAulNJZjAiwXx2aPAj39OoIyJFUXmDaE= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230616031450-0b2c9351a717/go.mod h1:ng62uGMGXyQSeuxePG5gJAMtip4Rnspu5Tu7hgvaXns= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230616032216-378bc19f3742 h1:qEbzwVDz1w2ewNHu+vipzV+a804wmwRWe+0vnhCbJr4= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230616032216-378bc19f3742/go.mod h1:ng62uGMGXyQSeuxePG5gJAMtip4Rnspu5Tu7hgvaXns= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230620005911-15ba3e93d621 h1:9Hzdn13l9U0RJn9mMXsZQr+jsmsgy3zQFsBHPSOJnxM= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230620005911-15ba3e93d621/go.mod h1:ng62uGMGXyQSeuxePG5gJAMtip4Rnspu5Tu7hgvaXns= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230621051330-0d8752e66161 h1:sgixcFwdLOqcvwqTaKcsMEepXsLmNEgaybyur3QHRgk= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230621051330-0d8752e66161/go.mod h1:ng62uGMGXyQSeuxePG5gJAMtip4Rnspu5Tu7hgvaXns= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230621052811-06ef97f11d22 h1:DImSGNxZrc+Q4WlS1OKMsLAScEfDYLX4XMJdjAaVnXc= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230621052811-06ef97f11d22/go.mod h1:ng62uGMGXyQSeuxePG5gJAMtip4Rnspu5Tu7hgvaXns= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230710081612-3024a17b540f h1:MMA/6fqn76zSOkUQzG8v+IbWvrtY1mXN5xF1WOZonVc= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230710081612-3024a17b540f/go.mod h1:rn6NA28Mej+qgLNx/Bu2wsdGyIycmacqlNP6gUXX2a0= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230710084625-dd05ebf6ceb9 h1:dizJeTf3xt7wEeq72sYqlgdy7an8kezA6JuqALKPCBQ= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230710084625-dd05ebf6ceb9/go.mod h1:rn6NA28Mej+qgLNx/Bu2wsdGyIycmacqlNP6gUXX2a0= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230710085335-ead6543d95f9 h1:zJ+33DKEA6CObPii5c5l5IbUIws31+Ni5NzzC3oYRLw= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230710085335-ead6543d95f9/go.mod h1:rn6NA28Mej+qgLNx/Bu2wsdGyIycmacqlNP6gUXX2a0= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230710085810-8173216e9574 h1:Ha0d/sv/MzC3ASCTXfe2tAFJieLNJmTCBL8aETEOY14= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230710085810-8173216e9574/go.mod h1:rn6NA28Mej+qgLNx/Bu2wsdGyIycmacqlNP6gUXX2a0= repositories.action2quare.com/ayo/gocommon v0.0.0-20230801051747-b501160efc3b h1:yV1cBeu0GFxkDD6TDxzKv/rM3OMtyt1JXpeqDF5IO3Y= repositories.action2quare.com/ayo/gocommon v0.0.0-20230801051747-b501160efc3b/go.mod h1:PdpZ16O1czKKxCxn+0AFNaEX/0kssYwC3G8jR0V7ybw=