all repos

onasty @ e9424c1

a one-time notes service

onasty/internal/oauth/google.go (view raw)

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