コールバック用のAPIを準備
func (h *GoogleAuthHandler) HandleGoogleCallback(c *gin.Context) {
code := c.Query("code")
err := c.Query("error")
ctx := c.Request.Context()
if err != "" {
c.Redirect(http.StatusFound, os.Getenv("APP_URL")+"/login")
return
}
googleUser, authError := h.GoogleAuthService.GetGoogleAuthUser(code)
if authError != nil {
c.Redirect(http.StatusFound, os.Getenv("APP_URL")+"/login")
return
}
// 後継処理を書く
}
コールバックで受け取ったcodeをdecodeし、accessTokenを使ってOpenID Connectへリクエストする
受け取ったresponseからuser情報を取得
package google
import (
"context"
"encoding/json"
"net/http"
"github.com/mizuko-dev/paput-api/config"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
)
type GoogleAuthUser struct {
Sub string `json:"sub"`
Email string `json:"email"`
VerifiedEmail bool `json:"verified_email"`
Name string `json:"name"`
GivenName string `json:"given_name"`
FamilyName string `json:"family_name"`
Picture string `json:"picture"`
Locale string `json:"locale"`
}
type GoogleAuthService struct {
OAuthConfig *oauth2.Config
}
func NewGoogleAuthService() GoogleAuthService {
config, _ := config.LoadConfig()
oauthConfig := &oauth2.Config{
RedirectURL: config.Google.RedirectURL,
ClientID: config.Google.ClientID,
ClientSecret: config.Google.ClientSecret,
Scopes: []string{
"email",
"profile",
},
Endpoint: google.Endpoint,
}
return GoogleAuthService{
OAuthConfig: oauthConfig,
}
}
func (r *GoogleAuthService) GetGoogleAuthUser(code string) (*GoogleAuthUser, error) {
token, err := r.OAuthConfig.Exchange(context.Background(), code)
if err != nil {
return nil, err
}
client := &http.Client{}
req, _ := http.NewRequest("GET", "https://openidconnect.googleapis.com/v1/userinfo", nil)
req.Header.Set("Authorization", "Bearer "+token.AccessToken)
response, err := client.Do(req)
if err != nil {
return nil, err
}
defer response.Body.Close()
var GoogleAuthUser GoogleAuthUser
if err := json.NewDecoder(response.Body).Decode(&GoogleAuthUser); err != nil {
return nil, err
}
return &GoogleAuthUser, nil
}