1

I'm making an app that needs to send printing jobs through Google Cloud Printing to two printers owned by me (i.e., the printers are always the same one and does not belong to the user). I've set up the printers with Google Cloud Printing and it is now accessible from my Google Account. enter image description here

Now, how can I access this account's printers through the API? I have found some documentation here that says that I need to authenticate myself when making requests. It seems to me that the authentication should be done with OAuth2. But the instructions on how to do that are lacking for a beginner. I've gotten so far as to getting my OAuth client ID and secret (step 1 in the OAuth link). But for step 2, I have no idea what to do.

It says:

Before your application can access private data using a Google API, it must obtain an access token that grants access to that API. A single access token can grant varying degrees of access to multiple APIs.

But doesn't explain how to obtain this access token. I looked at this SO question where OP seems to have been able to get this access token, but I can't understand how he did it.

Could someone please explain how to get an access token to use with Google Cloud Printing? Or a good resource which explains how?

PS. The printing functionality is triggered by a firebase function. Would this help us get the access token, considering firebase is also made by Google?

Mangu
  • 3,160
  • 2
  • 25
  • 42
Sahand
  • 7,980
  • 23
  • 69
  • 137
  • did you get any success? I am looking for same solution. please check my question https://stackoverflow.com/questions/52968277/google-cloud-print-api-integration-in-my-application – Samir Bhatt Oct 24 '18 at 12:44

2 Answers2

1

I ran into the same issue and came up with this two-step solution:

  1. Create an OAuth2 client in your Google Cloud Console as described here and download its client credentials from the console and copy & past its json content to credJSON in the code snippet below.
  2. Run the code below.
    • Follow the auth link and authorize your OAuth2 client to access Googel Cloud Printers with your Google account.
    • Copy & paste the auth code to the script
    • Once you obtained a refresh token make sure to store it in the variable refreshToken
    • Don't forget to update the proxy name.
package main

import (
    "context"
    "fmt"
    "log"

    "github.com/google/cloud-print-connector/gcp"
    "github.com/google/cloud-print-connector/lib"
    "github.com/google/uuid"
    "golang.org/x/oauth2"
    "golang.org/x/oauth2/google"
)

var (
    credJSON     = ``
    refreshToken = ""

    // Find the proxy in the Advanced Details of your printer at https://www.google.com/cloudprint#printers
    proxy = "HP"
)

func main() {
    // Obtain the OAuth config
    config, err := google.ConfigFromJSON([]byte(credJSON), gcp.ScopeCloudPrint)
    if err != nil {
        log.Fatalf("Failed to obtain OAuth config: %v", err)
    }

    // If no request token is present, obtain a new one
    if refreshToken == "" {
        // Get the auth link
        authLink := config.AuthCodeURL(uuid.New().String(), oauth2.AccessTypeOffline)
        log.Printf("Follow the link to obtain an auth code: %s", authLink)

        fmt.Printf("Paste your auth code here: ")
        var code string
        fmt.Scanln(&code)

        // Get a token form the auth code
        token, err := config.Exchange(context.Background(), code, oauth2.AccessTypeOffline)
        if err != nil {
            log.Fatalf("Failed to obtain OAuth token: %v", err)
        }
        if token.RefreshToken != "" {
            refreshToken = token.RefreshToken
        } else {
            refreshToken = token.AccessToken
        }
        log.Printf("Refresh token: %s", refreshToken)
    }

    // Connect to Google Cloud Print
    jobCh := make(chan *lib.Job)
    client, err := gcp.NewGoogleCloudPrint(lib.DefaultConfig.GCPBaseURL, refreshToken, refreshToken, proxy, config.ClientID, config.ClientSecret, config.Endpoint.AuthURL, config.Endpoint.TokenURL, lib.DefaultConfig.NativeJobQueueSize, jobCh, true)
    if err != nil {
        log.Fatalf("Failed to connect to GCP: %v", err)
    }

    // List all printers
    printers, _, err := client.ListPrinters()
    if err != nil {
        log.Fatalf("Failed to list printers: %v", err)
    }
    for _, p := range printers {
        log.Printf("Name: %s UUID: %s", p.Name, p.UUID)
    }
}
user10595796
  • 134
  • 9
0

Please refer to following documentation:

https://developers.google.com/identity/protocols/OAuth2ServiceAccount?authuser=1

I followed the same steps specified in the doc and was able to obtain the access token. First make Google Service Account, select furnish new private key. You ll have service account email addresss and private key. Using these credentials, you can obtain your access token. Below is the source code in Golang , this ll surely help you.

package main

import (
"fmt"
"github.com/dgrijalva/jwt-go"
"net/http"
"encoding/json"
"bytes"
)

type MyCustomClaims struct {
    Scope string `json:"scope,omitempty"`
    jwt.StandardClaims
}

type Toke struct {
    Access string `json:"access_token,omitempty"`
    Type string `json:"token_type,omitempty"`
    Expire string `json:"expires_in,omitempty"`
}

func main() {

    key := []byte("<your private key>")

    key1, _ := jwt.ParseRSAPrivateKeyFromPEM(key)

    claims := MyCustomClaims{
        "https://www.googleapis.com/auth/cloudprint",
        jwt.StandardClaims{
            IssuedAt: <currrent-epoch-time>,         // eg 1234566000
            ExpiresAt: <currrent-epoch-time + 3600>, // 3600 secs = 1hour, so expires in 1 hour, eg 1234569600
            Issuer:    "<your service account email>",
            Audience: "https://www.googleapis.com/oauth2/v4/token",
        },
    }
    token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
    ss, err := token.SignedString(key1)
    if err != nil {
        fmt.Println(err)
    }

    fmt.Println(ss)
    url := "https://www.googleapis.com/oauth2/v4/token"
    any := "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=" + ss
    a := []byte(any)
    b := bytes.NewBuffer(a)
    var tok Toke

    req, err := http.NewRequest("POST", url, b)
    req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

    client := &http.Client{}

    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    } else {
        json.NewDecoder(resp.Body).Decode(&tok)
    }
    fmt.Println("----------- Access Token -----------------")
    fmt.Println("Access: ", tok.Access)
}