-
Notifications
You must be signed in to change notification settings - Fork 384
/
provider.go
129 lines (109 loc) · 4.57 KB
/
provider.go
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package provider
import (
"bytes"
"context"
"encoding/json"
"io"
"log"
"net/http"
"os"
"time"
"github.com/supabase/gotrue/internal/utilities"
"golang.org/x/oauth2"
)
var defaultTimeout time.Duration = time.Second * 10
func init() {
timeoutStr := os.Getenv("GOTRUE_INTERNAL_HTTP_TIMEOUT")
if timeoutStr != "" {
if timeout, err := time.ParseDuration(timeoutStr); err != nil {
log.Fatalf("error loading GOTRUE_INTERNAL_HTTP_TIMEOUT: %v", err.Error())
} else if timeout != 0 {
defaultTimeout = timeout
}
}
}
type Claims struct {
// Reserved claims
Issuer string `json:"iss,omitempty" structs:"iss,omitempty"`
Subject string `json:"sub,omitempty" structs:"sub,omitempty"`
Aud string `json:"aud,omitempty" structs:"aud,omitempty"`
Iat float64 `json:"iat,omitempty" structs:"iat,omitempty"`
Exp float64 `json:"exp,omitempty" structs:"exp,omitempty"`
// Default profile claims
Name string `json:"name,omitempty" structs:"name,omitempty"`
FamilyName string `json:"family_name,omitempty" structs:"family_name,omitempty"`
GivenName string `json:"given_name,omitempty" structs:"given_name,omitempty"`
MiddleName string `json:"middle_name,omitempty" structs:"middle_name,omitempty"`
NickName string `json:"nickname,omitempty" structs:"nickname,omitempty"`
PreferredUsername string `json:"preferred_username,omitempty" structs:"preferred_username,omitempty"`
Profile string `json:"profile,omitempty" structs:"profile,omitempty"`
Picture string `json:"picture,omitempty" structs:"picture,omitempty"`
Website string `json:"website,omitempty" structs:"website,omitempty"`
Gender string `json:"gender,omitempty" structs:"gender,omitempty"`
Birthdate string `json:"birthdate,omitempty" structs:"birthdate,omitempty"`
ZoneInfo string `json:"zoneinfo,omitempty" structs:"zoneinfo,omitempty"`
Locale string `json:"locale,omitempty" structs:"locale,omitempty"`
UpdatedAt string `json:"updated_at,omitempty" structs:"updated_at,omitempty"`
Email string `json:"email,omitempty" structs:"email,omitempty"`
EmailVerified bool `json:"email_verified,omitempty" structs:"email_verified,omitempty"`
Phone string `json:"phone,omitempty" structs:"phone,omitempty"`
PhoneVerified bool `json:"phone_verified,omitempty" structs:"phone_verified,omitempty"`
// Custom profile claims that are provider specific
CustomClaims map[string]interface{} `json:"custom_claims,omitempty" structs:"custom_claims,omitempty"`
// TODO: Deprecate in next major release
FullName string `json:"full_name,omitempty" structs:"full_name,omitempty"`
AvatarURL string `json:"avatar_url,omitempty" structs:"avatar_url,omitempty"`
Slug string `json:"slug,omitempty" structs:"slug,omitempty"`
ProviderId string `json:"provider_id,omitempty" structs:"provider_id,omitempty"`
UserNameKey string `json:"user_name,omitempty" structs:"user_name,omitempty"`
}
// Email is a struct that provides information on whether an email is verified or is the primary email address
type Email struct {
Email string
Verified bool
Primary bool
}
// UserProvidedData is a struct that contains the user's data returned from the oauth provider
type UserProvidedData struct {
Emails []Email
Metadata *Claims
}
// Provider is an interface for interacting with external account providers
type Provider interface {
AuthCodeURL(string, ...oauth2.AuthCodeOption) string
}
// OAuthProvider specifies additional methods needed for providers using OAuth
type OAuthProvider interface {
AuthCodeURL(string, ...oauth2.AuthCodeOption) string
GetUserData(context.Context, *oauth2.Token) (*UserProvidedData, error)
GetOAuthToken(string) (*oauth2.Token, error)
}
func chooseHost(base, defaultHost string) string {
if base == "" {
return "https://" + defaultHost
}
baseLen := len(base)
if base[baseLen-1] == '/' {
return base[:baseLen-1]
}
return base
}
func makeRequest(ctx context.Context, tok *oauth2.Token, g *oauth2.Config, url string, dst interface{}) error {
client := g.Client(ctx, tok)
client.Timeout = defaultTimeout
res, err := client.Get(url)
if err != nil {
return err
}
defer utilities.SafeClose(res.Body)
bodyBytes, _ := io.ReadAll(res.Body)
defer utilities.SafeClose(res.Body)
res.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
if res.StatusCode < http.StatusOK || res.StatusCode >= http.StatusMultipleChoices {
return httpError(res.StatusCode, string(bodyBytes))
}
if err := json.NewDecoder(res.Body).Decode(dst); err != nil {
return err
}
return nil
}