mirror of
https://github.com/Dvorinka/Bookra.git
synced 2026-06-03 20:13:00 +00:00
89 lines
2.1 KiB
Go
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
|
|
}
|