onasty/internal/oauth/google.go(view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
package oauth
import (
"bytes"
"context"
"encoding/json"
"io"
"net/http"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
)
var _ Provider = (*GoogleProvider)(nil)
const googleUserInfoEndpoint = "https://www.googleapis.com/oauth2/v3/userinfo"
type GoogleProvider struct {
config oauth2.Config
}
func NewGoogleProvider(clientID, secret, redirectURL string) GoogleProvider {
return GoogleProvider{
config: oauth2.Config{
ClientID: clientID,
ClientSecret: secret,
RedirectURL: redirectURL,
Endpoint: google.Endpoint,
Scopes: []string{
"https://www.googleapis.com/auth/userinfo.email",
},
},
}
}
func (g GoogleProvider) GetAuthURL(state string) string {
return g.config.AuthCodeURL(state)
}
func (g GoogleProvider) ExchangeCode(ctx context.Context, code string) (UserInfo, error) {
tok, err := g.config.Exchange(ctx, code)
if err != nil {
return UserInfo{}, err
}
client := g.config.Client(ctx, tok)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, googleUserInfoEndpoint, nil)
if err != nil {
return UserInfo{}, err
}
resp, err := client.Do(req)
if err != nil {
return UserInfo{}, err
}
defer resp.Body.Close()
b, err := io.ReadAll(resp.Body)
if err != nil {
return UserInfo{}, err
}
var data struct {
Sub string `json:"sub"`
Email string `json:"email"`
EmailVerified bool `json:"email_verified"`
}
if err := json.NewDecoder(bytes.NewReader(b)).Decode(&data); err != nil {
return UserInfo{}, err
}
return UserInfo{
Provider: "google",
ProviderID: data.Sub,
Email: data.Email,
EmailVerified: data.EmailVerified,
}, nil
}
|