onasty/internal/oauth/github.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"
"strconv"
"golang.org/x/oauth2"
"golang.org/x/oauth2/github"
)
var _ Provider = (*GitHubProvider)(nil)
const githubUserInfoEndpoint = "https://api.github.com/user"
type GitHubProvider struct {
config oauth2.Config
}
func NewGithubProvider(clientID, secret, redirectURL string) GitHubProvider {
return GitHubProvider{
config: oauth2.Config{
ClientID: clientID,
ClientSecret: secret,
RedirectURL: redirectURL,
Endpoint: github.Endpoint,
Scopes: []string{
"user:email",
},
},
}
}
func (g GitHubProvider) GetAuthURL(state string) string {
return g.config.AuthCodeURL(state)
}
func (g GitHubProvider) 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, githubUserInfoEndpoint, 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 {
ID int `json:"id"`
Email string `json:"email"`
}
if err := json.NewDecoder(bytes.NewReader(b)).Decode(&data); err != nil {
return UserInfo{}, err
}
return UserInfo{
Provider: "github",
ProviderID: strconv.Itoa(data.ID),
Email: data.Email,
EmailVerified: true,
}, nil
}
|