Files
Bookra/apps/auth-service/internal/oauth/google.go
T
Tomas Dvorak 48c3e15a38 cleanup
2026-05-05 09:48:07 +02:00

89 lines
2.1 KiB
Go

package oauth
import (
"bookra/apps/auth-service/internal/config"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
)
type GoogleUser struct {
ID string `json:"id"`
Email string `json:"email"`
Name string `json:"name"`
Picture string `json:"picture"`
VerifiedEmail bool `json:"verified_email"`
}
type GoogleProvider struct {
config *oauth2.Config
}
func NewGoogleProvider(cfg *config.Config) *GoogleProvider {
if cfg.GoogleClientID == "" || cfg.GoogleClientSecret == "" {
return nil
}
redirectURL := cfg.GoogleRedirectURL
if redirectURL == "" {
redirectURL = cfg.FrontendURL + "/auth/oauth/google/callback"
}
return &GoogleProvider{
config: &oauth2.Config{
ClientID: cfg.GoogleClientID,
ClientSecret: cfg.GoogleClientSecret,
RedirectURL: redirectURL,
Scopes: []string{
"openid",
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/userinfo.profile",
},
Endpoint: google.Endpoint,
},
}
}
func (p *GoogleProvider) Enabled() bool {
return p != nil && p.config != nil
}
func (p *GoogleProvider) GetAuthURL(state string) string {
return p.config.AuthCodeURL(state, oauth2.AccessTypeOnline)
}
func (p *GoogleProvider) ExchangeCode(ctx context.Context, code string) (*GoogleUser, error) {
token, err := p.config.Exchange(ctx, code)
if err != nil {
return nil, fmt.Errorf("exchange code: %w", err)
}
client := p.config.Client(ctx, token)
resp, err := client.Get("https://www.googleapis.com/oauth2/v2/userinfo")
if err != nil {
return nil, fmt.Errorf("fetch userinfo: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(resp.Body)
return nil, fmt.Errorf("userinfo returned %d: %s", resp.StatusCode, string(body))
}
var user GoogleUser
if err := json.NewDecoder(resp.Body).Decode(&user); err != nil {
return nil, fmt.Errorf("decode userinfo: %w", err)
}
return &user, nil
}
func (p *GoogleProvider) ParseUser(user *GoogleUser) (providerID, email, name string) {
return user.ID, user.Email, user.Name
}