client icon indicating copy to clipboard operation
client copied to clipboard

Why is `x-goog-api-key` used instead of the `Authorization` header?

Open kernusr opened this issue 9 months ago • 6 comments

https://github.com/google-gemini-php/client/blob/6dca9a5e6a6de39b230fe4593a8d041efd02e34e/src/Factory.php#L120-L122

Why not replace this code with the one below

if ($this->apiKey !== null) {
        $this->headers['Authorization'] = 'Bearer ' . trim($this->apiKey);
}

This approach is described in the documentation from Google https://ai.google.dev/gemini-api/docs/oauth#curl

For example, I use a proxy to access gemini api and it requires authorization only using the Authorization header. And most likely I'm not alone in this problem.

kernusr avatar Feb 14 '25 11:02 kernusr

@kernusr I don't think this is the same. I've tried it out locally and I get

Gemini\Exceptions\TransporterException  Client error: `POST https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp:streamGenerateContent` resulted in a `401 Unauthorized` response.

The page you linked uses OAuth access tokens and not API key.

Plytas avatar Feb 14 '25 11:02 Plytas

However, this approach works if you acquire needed scopes and use access token. It might be a good addition to the package to provide alternative authentication methods. This would open up a possibility to let your clients authenticate via OAuth and perform LLM generation on their behalf.

What do you think @aydinfatih?

@kernusr would you be willing to open up a PR?

Plytas avatar Feb 14 '25 11:02 Plytas

However, this approach works if you acquire needed scopes and use access token. It might be a good addition to the package to provide alternative authentication methods. This would open up a possibility to let your clients authenticate via OAuth and perform LLM generation on their behalf.

What do you think @aydinfatih?

@kernusr would you be willing to open up a PR?

I have a few options that I could suggest:

  1. Just install the 2nd header, along with `x-goog-api-key``
if ($this->apiKey !== null) {
        $this->headers['x-goog-api-key'] = trim($this->apiKey); 
        $this->headers['Authorization'] = 'Bearer ' . trim($this->apiKey);
}

But I'm not sure what kind of detrimental impact this might have in different scenarios.

  1. Add the $oauthKey property and the withOauthKey() method to the \Gemini\Factory class This way, the static call of the instance with Gemini::client() will become inapplicable for users with Oauth Authentification. It will be possible to obtain a client instance only through the Factory:
$client = Gemini::factory()
    ->withOauthKey('sk-****')
    ->make();

kernusr avatar Feb 14 '25 14:02 kernusr

I am more inclined to the second option, as it guarantees more transparent behavior. If you help me with the choice, I will gladly contribute

kernusr avatar Feb 14 '25 14:02 kernusr

I'm not a maintainer of this package, so I can only give my opinion. I also think that 2nd option would be better, with method name being withAccessToken().

Plytas avatar Feb 14 '25 14:02 Plytas

withAccessToken

Oh yeah! That's more accurate! Thanks for the tip.

kernusr avatar Feb 14 '25 14:02 kernusr

Closing due to inactivity. @kernusr feel free to re-open if this is something you still need.

Plytas avatar Jun 09 '25 12:06 Plytas