package core import ( "encoding/json" "errors" "log" "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" ) func (mg *Maingate) platform_firebaseauth_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") // 무조껀 SDK 있어야됨 if withSDK != "1" { return } //fmt.Println("existid =>", existid) if existid != "" { //기존 계정이 있는 경우에는 그 계정 부터 조회한다. info, err := mg.getUserTokenWithCheck(AuthPlatformFirebaseAuth, existid, browserinfo) if err == nil { if info.token != "" { params := url.Values{} params.Add("id", existid) params.Add("authtype", AuthPlatformFirebaseAuth) if withSDK == "1" { w.Write([]byte("?" + params.Encode())) } return } } } sessionkey := mg.GeneratePlatformLoginNonceKey() nonce := mg.GeneratePlatformLoginNonceKey() mg.mongoClient.Delete(CollectionPlatformLoginToken, bson.M{ "platform": AuthPlatformFirebaseAuth, "key": sessionkey, }) _, _, err = mg.mongoClient.Update(CollectionPlatformLoginToken, bson.M{ "_id": primitive.NewObjectID(), }, bson.M{ "$setOnInsert": bson.M{ "platform": AuthPlatformFirebaseAuth, "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())) } } type FirebaseSDKAuthInfo struct { MemberId string `json:"id"` Code string `json:"code"` State string `json:"state"` Nickname string `json:"nickname"` Provider string `json:"provider"` ProviderId string `json:"providerId"` Email string `json:"email"` PhotoUrl string `json:"photourl"` PhoneNumber string `json:"phonenumber"` } func (mg *Maingate) platform_firebaseauth_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 FirebaseSDKAuthInfo 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_firebaseauth_authorize_raw(w, brinfo, authinfo.Code, authinfo.State, cookie.Value, authinfo.MemberId, authinfo.Nickname, authinfo.Provider, authinfo.ProviderId, authinfo.Email, authinfo.PhotoUrl, authinfo.PhoneNumber) 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_firebaseauth_authorize_raw(w http.ResponseWriter, brinfo, code, state, cookieSessionKey, memberId, nickname, provider, providerId, email, photourl, phonenumber string) (bool, string) { found, err := mg.mongoClient.FindOne(CollectionPlatformLoginToken, bson.M{ "platform": AuthPlatformFirebaseAuth, "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, "" } _, err = mg.firebaseAppClient.VerifyIDToken(mg.firebaseAppContext, code) if err != nil { log.Println("error verifying ID token:", err) return false, "" } // log.Println("Verified ID token: ", token) // log.Println("Verified ID token: ", token.UID) acceestoken_expire_time := time.Date(2999, 1, int(time.January), 0, 0, 0, 0, time.UTC).Unix() if memberId != "" && provider != "" && providerId != "" { var info usertokeninfo info.platform = AuthPlatformFirebaseAuth info.userid = memberId info.token = code info.brinfo = brinfo info.accesstoken = "" info.accesstoken_expire_time = acceestoken_expire_time mg.setUserToken(info) mg.mongoClient.Delete(CollectionFirebaseUserInfo, bson.M{ "firebaseuserid": info.userid, }) _, _, err := mg.mongoClient.Update(CollectionFirebaseUserInfo, bson.M{ "_id": primitive.NewObjectID(), }, bson.M{ "$setOnInsert": bson.M{ "firebaseuserid": memberId, "firebasenickname": nickname, "firebaseprovider": provider, "firebaseproviderId": providerId, "firebaseemail": email, "firebasephotourl": photourl, "firebasephonenumber": phonenumber, "updatetime": time.Now(), }, }, options.Update().SetUpsert(true)) if err != nil { logger.Error(err) } params := url.Values{} params.Add("id", memberId) params.Add("authtype", AuthPlatformFirebaseAuth) return true, params.Encode() } return false, "" } func (mg *Maingate) platform_firebase_getuserinfo(info usertokeninfo) (bool, string, string) { found, err := mg.mongoClient.FindOne(CollectionFirebaseUserInfo, bson.M{ "firebaseuserid": info.userid, }) if err != nil { logger.Error(err) return false, "", "" } if found == nil { logger.Error(errors.New("firebase info not found: " + info.userid)) return false, "", "" } _, err = mg.firebaseAppClient.VerifyIDToken(mg.firebaseAppContext, info.token) if err != nil { log.Println("error verifying ID token:", err) return false, "", "" } tempEmail := found["firebaseemail"].(string) return true, info.userid, tempEmail }