在@JohnHanley 提到只有在 IAP 后面运行时才会显示标头后,我才能够完成这项工作。在本地开发过程中您看不到它们。
在部署一个简单的临时路由后,我可以看到它们,/headers
该路由循环通过它们并写入 ResponseWriter。 X-Goog-Authenticated-User-Id
,X-Goog-Authenticated-User-Email
和X-Goog-Iap-Jwt-Assertion
.
import (
"fmt"
"net/http"
"github.com/rs/zerolog/log"
)
func headersHandler(w http.ResponseWriter, r *http.Request) {
log.Info().Msg("Entering headersHandler")
fmt.Fprintf(w, "Request Headers\n\n")
log.Debug().Msg("Request Headers:")
for name, values := range r.Header {
log.Debug().Interface(name, values).Send()
fmt.Fprintf(w, "%s = %s\n", name, values)
}
}
这是一条临时路线。一旦我可以确认标题,我就删除了它。
此外,我必须为托管我的 Web 应用程序的 ProjectId 启用 Google 的People API。
之后,我使用 Go 包进行了测试google.golang.org/api/people/v1
,发现使用当前经过身份验证的用户的约定people/me
在我的情况下不起作用,因为它返回了正在使用的服务帐户。相反,我必须以编程方式填写用户 id people/userid
。然后它起作用了。
对于我的用例,我创建了一个/user
路由来返回用户信息的子集,即姓名、电子邮件、照片 url。
结构:
type GoogleUser struct {
Name string `json:"name"`
Email string `json:"email"`
PhotoUrl string `json:"photo_url"`
}
处理程序:
func userHandler(w http.ResponseWriter, r *http.Request) {
log.Info().Msg("Entering userHandler")
var err error
// Make sure this is a valid API request
// Request header Content-Type: application/json must be present
if !ValidAPIRequest(r) {
err = writeJSONError(w, ResponseStatusNotFound("Not found"))
if err != nil {
log.Error().Msg(err.Error())
}
return
}
// Extract user id from header
var userId string = r.Header.Get("X-Goog-Authenticated-User-Id")
if userId != "" {
userId = strings.ReplaceAll(userId, "accounts.google.com:", "")
}
// Extract user email from header
var userEmail string = r.Header.Get("X-Goog-Authenticated-User-Email")
if userEmail != "" {
userEmail = strings.ReplaceAll(userEmail, "accounts.google.com:", "")
}
// Get the currently authenticated Google user
googleUser, err := GetCurrentGoogleUser(userId, userEmail)
if err != nil {
log.Error().Msg(err.Error())
err = writeJSONError(w, ResponseStatusInternalError(err.Error()))
if err != nil {
log.Error().Msg(err.Error())
}
return
}
// Write the JSON response
err = writeJSONGoogleUser(w, http.StatusOK, &googleUser)
if err != nil {
log.Error().Msg(err.Error())
}
}
谷歌人员 API:
func GetCurrentGoogleUser(userId string, userEmail string) (GoogleUser, error) {
// Pre-conditions
if userId == "" {
return GoogleUser{}, errors.New("userId is blank")
}
if userEmail == "" {
return GoogleUser{}, errors.New("userEmail is blank")
}
log.Debug().
Str("userId", userId).
Str("userEmail", userEmail).
Send()
ctx := context.Background()
// Instantiate a new People service
peopleService, err := people.NewService(ctx, option.WithAPIKey(GoogleAPIKey))
if err != nil {
return GoogleUser{}, err
}
// Define the resource name using the user id
var resourceName string = fmt.Sprintf("people/%s", userId)
// Get the user profile
profile, err := peopleService.People.Get(resourceName).PersonFields("names,photos").Do()
if err != nil {
return GoogleUser{}, err
}
log.Debug().
Interface("profile", profile).
Send()
return GoogleUser{Name: profile.Names[0].DisplayName, Email: userEmail, PhotoUrl: profile.Photos[0].Url}, nil
}