duanhua9398 2016-09-20 15:54
浏览 63
已采纳

在Go中验证Firebase实时数据库的服务帐户

I'm trying to use the new Firebase Realtime Database for a simple logging application. All interraction with the database will be from my server, so I only need one account that can read/write anything.

As far as I can tell (the documentation is awful - there's plenty of it but it contradicts itself and half of it is for the 'old' Firebase, and often it is in some random language that you aren't using), I need to create a service account and then create a JWT token using OAuth. Fortunately Go has some nice built in libraries for this. Here is my code:

const firebasePostUrl = "https://my-product-logging.firebaseio.com/tests.json"

// Obtained from the Google Cloud API Console
var firebaseServiceAccount map[string]string = map[string]string{
    "type":                        "service_account",
    "project_id":                  "my-product-logging",
    "private_key_id":              "1c35ac0c501617b8f1610113c492a5d3321f4318",
    "private_key":                 "-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoblahblahhwWlteuRDrsxmRq+8
cDGMKcXyDHl3nWdIrWqJcDw=
-----END PRIVATE KEY-----
",
    "client_email":                "log-user@my-product-logging.iam.gserviceaccount.com",
    "client_id":                   "101403085113430683797",
    "auth_uri":                    "https://accounts.google.com/o/oauth2/auth",
    "token_uri":                   "https://accounts.google.com/o/oauth2/token",
    "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
    "client_x509_cert_url":        "https://www.googleapis.com/robot/v1/metadata/x509/log-user%40my-product-logging.iam.gserviceaccount.com",
}

func firebaseClient() *http.Client {
    jwtConfig := jwt.Config{
        // Email is the OAuth client identifier used when communicating with
        // the configured OAuth provider.
        Email: firebaseServiceAccount["client_email"],

        // PrivateKey contains the contents of an RSA private key or the
        // contents of a PEM file that contains a private key. The provided
        // private key is used to sign JWT payloads.
        // PEM containers with a passphrase are not supported.
        // Use the following command to convert a PKCS 12 file into a PEM.
        //
        //    $ openssl pkcs12 -in key.p12 -out key.pem -nodes
        //
        PrivateKey: []byte(firebaseServiceAccount["private_key"]),

        // PrivateKeyID contains an optional hint indicating which key is being
        // used.
        PrivateKeyID: firebaseServiceAccount["private_key_id"],

        // Subject is the optional user to impersonate.
        Subject: "",

        // Scopes optionally specifies a list of requested permission scopes.
        Scopes: []string{
            "https://www.googleapis.com/auth/devstorage.readonly",
        },

        // TokenURL is the endpoint required to complete the 2-legged JWT flow.
        TokenURL: firebaseServiceAccount["token_uri"],

        // Expires optionally specifies how long the token is valid for.
        Expires: 0,
    }

    ctx := context.Background()
    return jwtConfig.Client(ctx)
}

func firebaseFunc() {

    authedClient := firebaseClient()

    msg := map[string]string{
        "hello": "there",
        "every": "one",
    }

    data, err := json.Marshal(msg)
    if err != nil {
        log.Fatal("JSON Marshall Error: ", err)
        continue
    }

    resp, err := authedClient.Post(firebasePostUrl, "application/json", bytes.NewReader(data))
    if err != nil {
        log.Fatal("Firebase Error: ", err)
        continue
    }

    log.Print("Firebase Response Code: ", resp.StatusCode)
}

The problem is, I always get this error:

{
  "error" : "invalid_scope",
  "error_description" : "https://www.googleapis.com/auth/devstorage.readonly is not a valid audience string."
}

I assume it is a type that the error is invalid_scope, and the description says it is an invalid audience (I assume the JWT aud parameter).

What do I use as my scope to allow me to read/write the Firebase Database (using the default "auth != null" rules)?

Edit: I found the answer here finally:

https://www.googleapis.com/auth/firebase

However now it gives me a 403 response when actually doing the post.

{
  "error" : "Permission denied."
}
  • 写回答

1条回答 默认 最新

  • dsf4354353452 2016-09-20 16:25
    关注

    Ugh, I found the undocumented answer here. Currently you also need this scope:

    https://www.googleapis.com/auth/userinfo.email
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?