Create a project using Google Cloud API (Golang)

Jason Choi
3 min readJun 28, 2021

A hard story

  1. The Goal: create a project using Google Cloud API on server side, without signing up
  2. middle Goal: get refresh token for user
  3. code

3–1. get user info & refresh token, for the first time(The code will no longer be used after acquiring user refresh token)

client := &http.Client{}// The API is called without code parameter at first, then it redirects to the uri with code parameter. So, when code parameter does not exist, it calls user authorization API, which shows Google sign in page on client. When code parameter exists, it means that a user has signed in already, so call token fetch API then.// check if code parameter exists on urikeys, ok := r.URL.Query()["code"]if !ok || len(keys[0]) < 1 {// user auth: call user authorization APIbaseUrl, err := url.Parse("https://accounts.google.com/o/oauth2/v2/auth")if err != nil {  fmt.Println("Malformed URL: ", err.Error())  return } params := url.Values{} params.Add("response_type", "code")// you can get client_id and client_secret(used later) once you
// create oAuth user authentication info at 'API and service'
// section of Google Cloud console
params.Add("client_id", "some_client_id") params.Add("redirect_uri", "http://localhost:8000/getrefreshtoken")// the list of scopes:
// https://developers.google.com/identity/protocols/oauth2/scopes
params.Add("scope", "https://www.googleapis.com/auth/cloud-platform")params.Add("access_type", "offline")// refer https://www.urlencoder.io/golang/ for url encodingbaseUrl.RawQuery = params.Encode() // Escape Query Parametershttp.Redirect(rw, r, baseUrl.String(), 300)} else {// when code exists: get refresh token - and save it to some safe place to use it latercode := keys[0]log.Println(code)data := map[string]interface{}{"code": code,"client_id": "some_client_id","client_secret": "some_client_secret","redirect_uri": "http://localhost:8000/getrefreshtoken","grant_type": "authorization_code",}jsonValue, _ := json.Marshal(data)req, err := http.NewRequest("POST", "https://oauth2.googleapis.com/token", bytes.NewBuffer(jsonValue))if err != nil {log.Println(err)return}resp, err := client.Do(req)
if err != nil {log.Println(err)return}// log.Println(resp)defer resp.Body.Close()type Res struct {AccessToken string `json:"access_token"`ExpiresIn int `json:"expires_in"`Scope string `json:"scope"`TokenType string `json:"token_type"`RefreshToken string `json:"refresh_token"`}var j Resif err != nil {log.Println(err)return}err = json.NewDecoder(resp.Body).Decode(&j)if err != nil {log.Println(err)return}// save refresh token to somewhere safelog.Println(j.RefreshToken)}

3–2. create project using API without signing in again

// 1. get access token client := &http.Client{}refreshToken := "some_refresh_token"// get new access tokendata := map[string]interface{}{“client_id”: “some_client_id",“client_secret”: “some_client_secret",“grant_type”: “refresh_token”, // string, just as it is“refresh_token”: refreshToken,}jsonValue, _ := json.Marshal(data)req, err := http.NewRequest(“POST”, “https://oauth2.googleapis.com/token", bytes.NewBuffer(jsonValue))if err != nil {log.Println(err)return}resp, err := client.Do(req)if err != nil {log.Println(err)return}// log.Println(resp)defer resp.Body.Close()type Res struct {AccessToken string `json:”access_token”`ExpiresIn int `json:”expires_in”`Scope string `json:”scope”`TokenType string `json:”token_type”`RefreshToken string `json:”refresh_token”`}var j Reserr = json.NewDecoder(resp.Body).Decode(&j)if err != nil {log.Println(err)return}log.Println(j.AccessToken)
// 2. create a project
data2 := map[string]interface{}{"projectId": "someprojectid",}jsonValue2, _ := json.Marshal(data2)req2, err := http.NewRequest("POST", "https://cloudresourcemanager.googleapis.com/v3/projects/", bytes.NewBuffer(jsonValue2))if err != nil {log.Println(err)return}req2.Header.Set("Content-Type", "application/json")req2.Header.Set("Authorization", "Bearer "+j.AccessToken)resp2, err := client.Do(req2)if err != nil {log.Println(err)return}b, _ := ioutil.ReadAll(resp2.Body)log.Println(string(b))

I know there is a way using Golang library — I’ll review on it later if possible.

Thank you for reading!

--

--