英文:
How to set up golang client for Google Calendar APIs using a service account
问题
我看到了很多关于为用户使用Google API客户端的文档,但很少有关于使用服务帐号的文档。这不是代表用户,我只是想使用客户端ID和客户端密钥来使Calendar API的客户端工作,这些信息将通过环境变量提供给我(我更喜欢不从文件中读取)。
以下是我目前的代码:
package main
import (
"context"
clientCredentials "golang.org/x/oauth2/clientcredentials"
google "golang.org/x/oauth2/google"
calendar "google.golang.org/api/calendar/v3"
apiOption "google.golang.org/api/option"
)
func main() {
config := &clientCredentials.Config{
ClientID: "<my_id>",
ClientSecret: "-----BEGIN PRIVATE KEY-----\n...",
TokenURL: google.Endpoint.TokenURL,
}
ctx := context.Background()
client := config.Client(ctx)
service, _ := calendar.NewService(ctx, apiOption.WithHTTPClient(client))
calendarList, err := service.CalendarList.List().Do()
}
但是我得到了以下错误:
Get "https://www.googleapis.com/calendar/v3/users/me/calendarList?alt=json&prettyPrint=false": oauth2: cannot fetch token: 400 Bad Request
Response: {
"error": "unsupported_grant_type",
"error_description": "Invalid grant_type: client_credentials"
}
非常感谢您的帮助!我对Golang、Oauth2和Google API都很新
英文:
I've seen lots of documentation on Google API clients for users, but very little on using a service account. This isn't on behalf of a user, I'm just trying to get a client working with the Calendar APIs using a client ID and client secret, which would be provided via environment variables for me (I'd prefer to not read from a file).
Here's what I have so far:
package main
import (
"context"
clientCredentials "golang.org/x/oauth2/clientcredentials"
google "golang.org/x/oauth2/google"
calendar "google.golang.org/api/calendar/v3"
apiOption "google.golang.org/api/option"
)
func main() {
config := &clientCredentials.Config{
ClientID: "<my_id>",
ClientSecret: "-----BEGIN PRIVATE KEY-----\n...",
TokenURL: google.Endpoint.TokenURL,
}
ctx := context.Background()
client := config.Client(ctx)
service, _ := calendar.NewService(ctx, apiOption.WithHTTPClient(client))
calendarList, err := service.CalendarList.List().Do()
}
But I'm getting the following error:
Get "https://www.googleapis.com/calendar/v3/users/me/calendarList?alt=json&prettyPrint=false": oauth2: cannot fetch token: 400 Bad Request
Response: {
"error": "unsupported_grant_type",
"error_description": "Invalid grant_type: client_credentials"
}
Any help here is greatly appreciated! I'm new to Golang, Oauth2, and Google APIs
答案1
得分: 1
我相信你的目标如下。
- 你想使用golang使用服务帐户访问Google日历。
在这种情况下,以下修改如何?
修改后的脚本:
package main
import (
"context"
"fmt"
calendar "google.golang.org/api/calendar/v3"
"google.golang.org/api/option"
)
func main() {
ctx := context.Background()
v := `{"type": "service_account", "private_key": "-----BEGIN PRIVATE KEY-----\n###\n-----END PRIVATE KEY-----\n", "client_email": "###"}`
service, _ := calendar.NewService(ctx, option.WithCredentialsJSON([]byte(v)))
calendarList, _ := service.CalendarList.List().Do()
fmt.Println(calendarList)
}
-
如果你想使用包含凭据信息的文件,请按以下方式进行修改。
service, _ := calendar.NewService(ctx, option.WithCredentialsFile(credentialFile))
注意:
-
如果你想检索你的账户的Google日历,请将你的Google日历与服务帐户的电子邮件共享。
-
Linda Lawton - DaImTo的评论:
Google日历不支持标准Google用户的服务帐户。你需要配置域范围的委派,并在你的Google Workspace帐户上模拟一个用户。以及如何将子添加到此代码中。
参考资料:
英文:
I believe your goal is as follows.
- You want to access Google Calendar using the service account with golang.
In this case, how about the following modification?
Modified script:
package main
import (
"context"
"fmt"
calendar "google.golang.org/api/calendar/v3"
"google.golang.org/api/option"
)
func main() {
ctx := context.Background()
v := `{"type": "service_account", "private_key": "-----BEGIN PRIVATE KEY-----\n###\n-----END PRIVATE KEY-----\n", "client_email": "###"}`
service, _ := calendar.NewService(ctx, option.WithCredentialsJSON([]byte(v)))
calendarList, _ := service.CalendarList.List().Do()
fmt.Println(calendarList)
}
-
If you want to use the file including the credential information, please modify it as follows.
service, _ := calendar.NewService(ctx, option.WithCredentialsFile(credentialFile))
Note:
-
If you want to retrieve the Google Calendar of your account, please share your Google Calendar with the email of the service account.
-
Linda Lawton - DaImTo's comment:
Google calendar doesn't support service account for standard google users. You need to configure domain wide delegation and impersonate a user on your google workspace account. and how to add the sub to this code.
References:
答案2
得分: 0
@Tanaike的答案让我找到了正确的方向。这是我最终使用的代码:
package main
import (
"context"
"encoding/json"
"fmt"
googleOauth "golang.org/x/oauth2/google"
calendar "google.golang.org/api/calendar/v3"
apiOption "google.golang.org/api/option"
)
var service *calendar.Service
// 注意,一些字段是可选的:
type GoogleAuthConfig struct {
Type string `json:"type"`
ProjectID string `json:"project_id,omitempty"`
ClientEmail string `json:"client_email"`
ClientID string `json:"client_id,omitempty"`
ClientSecret string `json:"private_key"`
ClientSecretID string `json:"private_key_id,omitempty"`
AuthURL string `json:"auth_uri,omitempty"`
TokenURL string `json:"token_uri,omitempty"`
AuthProviderCertURL string `json:"auth_provider_x509_cert_url,omitempty"`
ClientCertURL string `json:"client_x509_cert_url,omitempty"`
}
func main() {
authConfig := GoogleAuthConfig{
Type: "service_account",
ClientEmail: "account123@project-456.iam.gserviceaccount.com",
ClientID: "1234",
ClientSecret: "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
AuthURL: googleOauth.Endpoint.AuthURL,
TokenURL: googleOauth.Endpoint.TokenURL,
}
authConfigJson, err := json.Marshal(authConfig)
ctx := context.Background()
service, err = calendar.NewService(ctx, apiOption.WithCredentialsJSON([]byte(authConfigJson)))
}
注意,我不需要配置域委派或模拟用户;在将服务帐号添加到日历后,这个代码就可以正常工作。
在将帐号电子邮件添加到日历后,服务帐号仍然需要接受日历邀请。可以使用以下代码完成:
entry := calendar.CalendarListEntry{Id: calendarID}
service.CalendarList.Insert(&entry).Do()
请注意,这是你提供的代码的翻译版本。如果有任何问题,请告诉我。
英文:
The answer from @Tanaike got me on the right track. This is what I ended up using:
package main
import (
"context"
"encoding/json"
"fmt"
googleOauth "golang.org/x/oauth2/google"
calendar "google.golang.org/api/calendar/v3"
apiOption "google.golang.org/api/option"
)
var service *calendar.Service
// Note that some of the fields are optional:
type GoogleAuthConfig struct {
Type string `json:"type"`
ProjectID string `json:"project_id,omitempty"`
ClientEmail string `json:"client_email"`
ClientID string `json:"client_id,omitempty"`
ClientSecret string `json:"private_key"`
ClientSecretID string `json:"private_key_id,omitempty"`
AuthURL string `json:"auth_uri,omitempty"`
TokenURL string `json:"token_uri,omitempty"`
AuthProviderCertURL string `json:"auth_provider_x509_cert_url,omitempty"`
ClientCertURL string `json:"client_x509_cert_url,omitempty"`
}
func main() {
authConfig := GoogleAuthConfig{
Type: "service_account",
ClientEmail: "account123@project-456.iam.gserviceaccount.com",
ClientID: "1234",
ClientSecret: "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
AuthURL: googleOauth.Endpoint.AuthURL,
TokenURL: googleOauth.Endpoint.TokenURL,
}
authConfigJson, err := json.Marshal(authConfig)
ctx := context.Background()
service, err = calendar.NewService(ctx, apiOption.WithCredentialsJSON([]byte(authConfigJson)))
}
Note that I didn't have to configure domain-wide delegation or impersonate a user; this worked fine after I added the service account to the calendar.
Service accounts still need to accept calendar invites after you add the account email to the calendar. This can be done with the following:
entry := calendar.CalendarListEntry{Id: calendarID}
service.CalendarList.Insert(&entry).Do()
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论