merge v0.23.0-rc changes
This commit is contained in:
+14
-10
@@ -18,6 +18,10 @@ import (
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Providers[NameApple] = wrapFactory(NewAppleProvider)
|
||||
}
|
||||
|
||||
var _ Provider = (*Apple)(nil)
|
||||
|
||||
// NameApple is the unique name of the Apple provider.
|
||||
@@ -27,23 +31,23 @@ const NameApple string = "apple"
|
||||
//
|
||||
// [OIDC differences]: https://bitbucket.org/openid/connect/src/master/How-Sign-in-with-Apple-differs-from-OpenID-Connect.md
|
||||
type Apple struct {
|
||||
*baseProvider
|
||||
BaseProvider
|
||||
|
||||
jwksUrl string
|
||||
jwksURL string
|
||||
}
|
||||
|
||||
// NewAppleProvider creates a new Apple provider instance with some defaults.
|
||||
func NewAppleProvider() *Apple {
|
||||
return &Apple{
|
||||
baseProvider: &baseProvider{
|
||||
BaseProvider: BaseProvider{
|
||||
ctx: context.Background(),
|
||||
displayName: "Apple",
|
||||
pkce: true,
|
||||
scopes: []string{"name", "email"},
|
||||
authUrl: "https://appleid.apple.com/auth/authorize",
|
||||
tokenUrl: "https://appleid.apple.com/auth/token",
|
||||
authURL: "https://appleid.apple.com/auth/authorize",
|
||||
tokenURL: "https://appleid.apple.com/auth/token",
|
||||
},
|
||||
jwksUrl: "https://appleid.apple.com/auth/keys",
|
||||
jwksURL: "https://appleid.apple.com/auth/keys",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +55,7 @@ func NewAppleProvider() *Apple {
|
||||
//
|
||||
// API reference: https://developer.apple.com/documentation/sign_in_with_apple/tokenresponse.
|
||||
func (p *Apple) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
data, err := p.FetchRawUserData(token)
|
||||
data, err := p.FetchRawUserInfo(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -98,11 +102,11 @@ func (p *Apple) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// FetchRawUserData implements Provider.FetchRawUserData interface.
|
||||
// FetchRawUserInfo implements Provider.FetchRawUserInfo interface.
|
||||
//
|
||||
// Apple doesn't have a UserInfo endpoint and claims about users
|
||||
// are instead included in the "id_token" (https://openid.net/specs/openid-connect-core-1_0.html#id_tokenExample)
|
||||
func (p *Apple) FetchRawUserData(token *oauth2.Token) ([]byte, error) {
|
||||
func (p *Apple) FetchRawUserInfo(token *oauth2.Token) ([]byte, error) {
|
||||
idToken, _ := token.Extra("id_token").(string)
|
||||
|
||||
claims, err := p.parseAndVerifyIdToken(idToken)
|
||||
@@ -209,7 +213,7 @@ type jwk struct {
|
||||
}
|
||||
|
||||
func (p *Apple) fetchJWK(kid string) (*jwk, error) {
|
||||
req, err := http.NewRequestWithContext(p.ctx, "GET", p.jwksUrl, nil)
|
||||
req, err := http.NewRequestWithContext(p.ctx, "GET", p.jwksURL, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+73
-87
@@ -2,6 +2,7 @@ package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
@@ -9,17 +10,22 @@ import (
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
// AuthUser defines a standardized oauth2 user data structure.
|
||||
type AuthUser struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
AvatarUrl string `json:"avatarUrl"`
|
||||
AccessToken string `json:"accessToken"`
|
||||
RefreshToken string `json:"refreshToken"`
|
||||
Expiry types.DateTime `json:"expiry"`
|
||||
RawUser map[string]any `json:"rawUser"`
|
||||
// ProviderFactoryFunc defines a function for initializing a new OAuth2 provider.
|
||||
type ProviderFactoryFunc func() Provider
|
||||
|
||||
// Providers defines a map with all of the available OAuth2 providers.
|
||||
//
|
||||
// To register a new provider append a new entry in the map.
|
||||
var Providers = map[string]ProviderFactoryFunc{}
|
||||
|
||||
// NewProviderByName returns a new preconfigured provider instance by its name identifier.
|
||||
func NewProviderByName(name string) (Provider, error) {
|
||||
factory, ok := Providers[name]
|
||||
if !ok {
|
||||
return nil, errors.New("missing provider " + name)
|
||||
}
|
||||
|
||||
return factory(), nil
|
||||
}
|
||||
|
||||
// Provider defines a common interface for an OAuth2 client.
|
||||
@@ -61,104 +67,84 @@ type Provider interface {
|
||||
// SetClientSecret sets the provider client's app secret.
|
||||
SetClientSecret(secret string)
|
||||
|
||||
// RedirectUrl returns the end address to redirect the user
|
||||
// RedirectURL returns the end address to redirect the user
|
||||
// going through the OAuth flow.
|
||||
RedirectUrl() string
|
||||
RedirectURL() string
|
||||
|
||||
// SetRedirectUrl sets the provider's RedirectUrl.
|
||||
SetRedirectUrl(url string)
|
||||
// SetRedirectURL sets the provider's RedirectURL.
|
||||
SetRedirectURL(url string)
|
||||
|
||||
// AuthUrl returns the provider's authorization service url.
|
||||
AuthUrl() string
|
||||
// AuthURL returns the provider's authorization service url.
|
||||
AuthURL() string
|
||||
|
||||
// SetAuthUrl sets the provider's AuthUrl.
|
||||
SetAuthUrl(url string)
|
||||
// SetAuthURL sets the provider's AuthURL.
|
||||
SetAuthURL(url string)
|
||||
|
||||
// TokenUrl returns the provider's token exchange service url.
|
||||
TokenUrl() string
|
||||
// TokenURL returns the provider's token exchange service url.
|
||||
TokenURL() string
|
||||
|
||||
// SetTokenUrl sets the provider's TokenUrl.
|
||||
SetTokenUrl(url string)
|
||||
// SetTokenURL sets the provider's TokenURL.
|
||||
SetTokenURL(url string)
|
||||
|
||||
// UserApiUrl returns the provider's user info api url.
|
||||
UserApiUrl() string
|
||||
// UserInfoURL returns the provider's user info api url.
|
||||
UserInfoURL() string
|
||||
|
||||
// SetUserApiUrl sets the provider's UserApiUrl.
|
||||
SetUserApiUrl(url string)
|
||||
// SetUserInfoURL sets the provider's UserInfoURL.
|
||||
SetUserInfoURL(url string)
|
||||
|
||||
// Client returns an http client using the provided token.
|
||||
Client(token *oauth2.Token) *http.Client
|
||||
|
||||
// BuildAuthUrl returns a URL to the provider's consent page
|
||||
// BuildAuthURL returns a URL to the provider's consent page
|
||||
// that asks for permissions for the required scopes explicitly.
|
||||
BuildAuthUrl(state string, opts ...oauth2.AuthCodeOption) string
|
||||
BuildAuthURL(state string, opts ...oauth2.AuthCodeOption) string
|
||||
|
||||
// FetchToken converts an authorization code to token.
|
||||
FetchToken(code string, opts ...oauth2.AuthCodeOption) (*oauth2.Token, error)
|
||||
|
||||
// FetchRawUserData requests and marshalizes into `result` the
|
||||
// FetchRawUserInfo requests and marshalizes into `result` the
|
||||
// the OAuth user api response.
|
||||
FetchRawUserData(token *oauth2.Token) ([]byte, error)
|
||||
FetchRawUserInfo(token *oauth2.Token) ([]byte, error)
|
||||
|
||||
// FetchAuthUser is similar to FetchRawUserData, but normalizes and
|
||||
// FetchAuthUser is similar to FetchRawUserInfo, but normalizes and
|
||||
// marshalizes the user api response into a standardized AuthUser struct.
|
||||
FetchAuthUser(token *oauth2.Token) (user *AuthUser, err error)
|
||||
}
|
||||
|
||||
// NewProviderByName returns a new preconfigured provider instance by its name identifier.
|
||||
func NewProviderByName(name string) (Provider, error) {
|
||||
switch name {
|
||||
case NameGoogle:
|
||||
return NewGoogleProvider(), nil
|
||||
case NameFacebook:
|
||||
return NewFacebookProvider(), nil
|
||||
case NameGithub:
|
||||
return NewGithubProvider(), nil
|
||||
case NameGitlab:
|
||||
return NewGitlabProvider(), nil
|
||||
case NameDiscord:
|
||||
return NewDiscordProvider(), nil
|
||||
case NameTwitter:
|
||||
return NewTwitterProvider(), nil
|
||||
case NameMicrosoft:
|
||||
return NewMicrosoftProvider(), nil
|
||||
case NameSpotify:
|
||||
return NewSpotifyProvider(), nil
|
||||
case NameKakao:
|
||||
return NewKakaoProvider(), nil
|
||||
case NameTwitch:
|
||||
return NewTwitchProvider(), nil
|
||||
case NameStrava:
|
||||
return NewStravaProvider(), nil
|
||||
case NameGitee:
|
||||
return NewGiteeProvider(), nil
|
||||
case NameLivechat:
|
||||
return NewLivechatProvider(), nil
|
||||
case NameGitea:
|
||||
return NewGiteaProvider(), nil
|
||||
case NameOIDC:
|
||||
return NewOIDCProvider(), nil
|
||||
case NameOIDC + "2":
|
||||
return NewOIDCProvider(), nil
|
||||
case NameOIDC + "3":
|
||||
return NewOIDCProvider(), nil
|
||||
case NameApple:
|
||||
return NewAppleProvider(), nil
|
||||
case NameInstagram:
|
||||
return NewInstagramProvider(), nil
|
||||
case NameVK:
|
||||
return NewVKProvider(), nil
|
||||
case NameYandex:
|
||||
return NewYandexProvider(), nil
|
||||
case NamePatreon:
|
||||
return NewPatreonProvider(), nil
|
||||
case NameMailcow:
|
||||
return NewMailcowProvider(), nil
|
||||
case NameBitbucket:
|
||||
return NewBitbucketProvider(), nil
|
||||
case NamePlanningcenter:
|
||||
return NewPlanningcenterProvider(), nil
|
||||
default:
|
||||
return nil, errors.New("Missing provider " + name)
|
||||
// wrapFactory is a helper that wraps a Provider specific factory
|
||||
// function and returns its result as Provider interface.
|
||||
func wrapFactory[T Provider](factory func() T) ProviderFactoryFunc {
|
||||
return func() Provider {
|
||||
return factory()
|
||||
}
|
||||
}
|
||||
|
||||
// AuthUser defines a standardized OAuth2 user data structure.
|
||||
type AuthUser struct {
|
||||
Expiry types.DateTime `json:"expiry"`
|
||||
RawUser map[string]any `json:"rawUser"`
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
AvatarURL string `json:"avatarURL"`
|
||||
AccessToken string `json:"accessToken"`
|
||||
RefreshToken string `json:"refreshToken"`
|
||||
|
||||
// @todo
|
||||
// deprecated: use AvatarURL instead
|
||||
// AvatarUrl will be removed after dropping v0.22 support
|
||||
AvatarUrl string `json:"avatarUrl"`
|
||||
}
|
||||
|
||||
// MarshalJSON implements the [json.Marshaler] interface.
|
||||
//
|
||||
// @todo remove after dropping v0.22 support
|
||||
func (au AuthUser) MarshalJSON() ([]byte, error) {
|
||||
type alias AuthUser // prevent recursion
|
||||
|
||||
au2 := alias(au)
|
||||
au2.AvatarURL = au.AvatarURL // ensure that the legacy field is populated
|
||||
|
||||
return json.Marshal(au2)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,14 @@ import (
|
||||
"github.com/pocketbase/pocketbase/tools/auth"
|
||||
)
|
||||
|
||||
func TestProvidersCount(t *testing.T) {
|
||||
expected := 25
|
||||
|
||||
if total := len(auth.Providers); total != expected {
|
||||
t.Fatalf("Expected %d providers, got %d", expected, total)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewProviderByName(t *testing.T) {
|
||||
var err error
|
||||
var p auth.Provider
|
||||
|
||||
+57
-57
@@ -9,147 +9,147 @@ import (
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
// baseProvider defines common fields and methods used by OAuth2 client providers.
|
||||
type baseProvider struct {
|
||||
// BaseProvider defines common fields and methods used by OAuth2 client providers.
|
||||
type BaseProvider struct {
|
||||
ctx context.Context
|
||||
clientId string
|
||||
clientSecret string
|
||||
displayName string
|
||||
redirectUrl string
|
||||
authUrl string
|
||||
tokenUrl string
|
||||
userApiUrl string
|
||||
redirectURL string
|
||||
authURL string
|
||||
tokenURL string
|
||||
userInfoURL string
|
||||
scopes []string
|
||||
pkce bool
|
||||
}
|
||||
|
||||
// Context implements Provider.Context() interface method.
|
||||
func (p *baseProvider) Context() context.Context {
|
||||
func (p *BaseProvider) Context() context.Context {
|
||||
return p.ctx
|
||||
}
|
||||
|
||||
// SetContext implements Provider.SetContext() interface method.
|
||||
func (p *baseProvider) SetContext(ctx context.Context) {
|
||||
func (p *BaseProvider) SetContext(ctx context.Context) {
|
||||
p.ctx = ctx
|
||||
}
|
||||
|
||||
// PKCE implements Provider.PKCE() interface method.
|
||||
func (p *baseProvider) PKCE() bool {
|
||||
func (p *BaseProvider) PKCE() bool {
|
||||
return p.pkce
|
||||
}
|
||||
|
||||
// SetPKCE implements Provider.SetPKCE() interface method.
|
||||
func (p *baseProvider) SetPKCE(enable bool) {
|
||||
func (p *BaseProvider) SetPKCE(enable bool) {
|
||||
p.pkce = enable
|
||||
}
|
||||
|
||||
// DisplayName implements Provider.DisplayName() interface method.
|
||||
func (p *baseProvider) DisplayName() string {
|
||||
func (p *BaseProvider) DisplayName() string {
|
||||
return p.displayName
|
||||
}
|
||||
|
||||
// SetDisplayName implements Provider.SetDisplayName() interface method.
|
||||
func (p *baseProvider) SetDisplayName(displayName string) {
|
||||
func (p *BaseProvider) SetDisplayName(displayName string) {
|
||||
p.displayName = displayName
|
||||
}
|
||||
|
||||
// Scopes implements Provider.Scopes() interface method.
|
||||
func (p *baseProvider) Scopes() []string {
|
||||
func (p *BaseProvider) Scopes() []string {
|
||||
return p.scopes
|
||||
}
|
||||
|
||||
// SetScopes implements Provider.SetScopes() interface method.
|
||||
func (p *baseProvider) SetScopes(scopes []string) {
|
||||
func (p *BaseProvider) SetScopes(scopes []string) {
|
||||
p.scopes = scopes
|
||||
}
|
||||
|
||||
// ClientId implements Provider.ClientId() interface method.
|
||||
func (p *baseProvider) ClientId() string {
|
||||
func (p *BaseProvider) ClientId() string {
|
||||
return p.clientId
|
||||
}
|
||||
|
||||
// SetClientId implements Provider.SetClientId() interface method.
|
||||
func (p *baseProvider) SetClientId(clientId string) {
|
||||
func (p *BaseProvider) SetClientId(clientId string) {
|
||||
p.clientId = clientId
|
||||
}
|
||||
|
||||
// ClientSecret implements Provider.ClientSecret() interface method.
|
||||
func (p *baseProvider) ClientSecret() string {
|
||||
func (p *BaseProvider) ClientSecret() string {
|
||||
return p.clientSecret
|
||||
}
|
||||
|
||||
// SetClientSecret implements Provider.SetClientSecret() interface method.
|
||||
func (p *baseProvider) SetClientSecret(secret string) {
|
||||
func (p *BaseProvider) SetClientSecret(secret string) {
|
||||
p.clientSecret = secret
|
||||
}
|
||||
|
||||
// RedirectUrl implements Provider.RedirectUrl() interface method.
|
||||
func (p *baseProvider) RedirectUrl() string {
|
||||
return p.redirectUrl
|
||||
// RedirectURL implements Provider.RedirectURL() interface method.
|
||||
func (p *BaseProvider) RedirectURL() string {
|
||||
return p.redirectURL
|
||||
}
|
||||
|
||||
// SetRedirectUrl implements Provider.SetRedirectUrl() interface method.
|
||||
func (p *baseProvider) SetRedirectUrl(url string) {
|
||||
p.redirectUrl = url
|
||||
// SetRedirectURL implements Provider.SetRedirectURL() interface method.
|
||||
func (p *BaseProvider) SetRedirectURL(url string) {
|
||||
p.redirectURL = url
|
||||
}
|
||||
|
||||
// AuthUrl implements Provider.AuthUrl() interface method.
|
||||
func (p *baseProvider) AuthUrl() string {
|
||||
return p.authUrl
|
||||
// AuthURL implements Provider.AuthURL() interface method.
|
||||
func (p *BaseProvider) AuthURL() string {
|
||||
return p.authURL
|
||||
}
|
||||
|
||||
// SetAuthUrl implements Provider.SetAuthUrl() interface method.
|
||||
func (p *baseProvider) SetAuthUrl(url string) {
|
||||
p.authUrl = url
|
||||
// SetAuthURL implements Provider.SetAuthURL() interface method.
|
||||
func (p *BaseProvider) SetAuthURL(url string) {
|
||||
p.authURL = url
|
||||
}
|
||||
|
||||
// TokenUrl implements Provider.TokenUrl() interface method.
|
||||
func (p *baseProvider) TokenUrl() string {
|
||||
return p.tokenUrl
|
||||
// TokenURL implements Provider.TokenURL() interface method.
|
||||
func (p *BaseProvider) TokenURL() string {
|
||||
return p.tokenURL
|
||||
}
|
||||
|
||||
// SetTokenUrl implements Provider.SetTokenUrl() interface method.
|
||||
func (p *baseProvider) SetTokenUrl(url string) {
|
||||
p.tokenUrl = url
|
||||
// SetTokenURL implements Provider.SetTokenURL() interface method.
|
||||
func (p *BaseProvider) SetTokenURL(url string) {
|
||||
p.tokenURL = url
|
||||
}
|
||||
|
||||
// UserApiUrl implements Provider.UserApiUrl() interface method.
|
||||
func (p *baseProvider) UserApiUrl() string {
|
||||
return p.userApiUrl
|
||||
// UserInfoURL implements Provider.UserInfoURL() interface method.
|
||||
func (p *BaseProvider) UserInfoURL() string {
|
||||
return p.userInfoURL
|
||||
}
|
||||
|
||||
// SetUserApiUrl implements Provider.SetUserApiUrl() interface method.
|
||||
func (p *baseProvider) SetUserApiUrl(url string) {
|
||||
p.userApiUrl = url
|
||||
// SetUserInfoURL implements Provider.SetUserInfoURL() interface method.
|
||||
func (p *BaseProvider) SetUserInfoURL(url string) {
|
||||
p.userInfoURL = url
|
||||
}
|
||||
|
||||
// BuildAuthUrl implements Provider.BuildAuthUrl() interface method.
|
||||
func (p *baseProvider) BuildAuthUrl(state string, opts ...oauth2.AuthCodeOption) string {
|
||||
// BuildAuthURL implements Provider.BuildAuthURL() interface method.
|
||||
func (p *BaseProvider) BuildAuthURL(state string, opts ...oauth2.AuthCodeOption) string {
|
||||
return p.oauth2Config().AuthCodeURL(state, opts...)
|
||||
}
|
||||
|
||||
// FetchToken implements Provider.FetchToken() interface method.
|
||||
func (p *baseProvider) FetchToken(code string, opts ...oauth2.AuthCodeOption) (*oauth2.Token, error) {
|
||||
func (p *BaseProvider) FetchToken(code string, opts ...oauth2.AuthCodeOption) (*oauth2.Token, error) {
|
||||
return p.oauth2Config().Exchange(p.ctx, code, opts...)
|
||||
}
|
||||
|
||||
// Client implements Provider.Client() interface method.
|
||||
func (p *baseProvider) Client(token *oauth2.Token) *http.Client {
|
||||
func (p *BaseProvider) Client(token *oauth2.Token) *http.Client {
|
||||
return p.oauth2Config().Client(p.ctx, token)
|
||||
}
|
||||
|
||||
// FetchRawUserData implements Provider.FetchRawUserData() interface method.
|
||||
func (p *baseProvider) FetchRawUserData(token *oauth2.Token) ([]byte, error) {
|
||||
req, err := http.NewRequestWithContext(p.ctx, "GET", p.userApiUrl, nil)
|
||||
// FetchRawUserInfo implements Provider.FetchRawUserInfo() interface method.
|
||||
func (p *BaseProvider) FetchRawUserInfo(token *oauth2.Token) ([]byte, error) {
|
||||
req, err := http.NewRequestWithContext(p.ctx, "GET", p.userInfoURL, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return p.sendRawUserDataRequest(req, token)
|
||||
return p.sendRawUserInfoRequest(req, token)
|
||||
}
|
||||
|
||||
// sendRawUserDataRequest sends the specified user data request and return its raw response body.
|
||||
func (p *baseProvider) sendRawUserDataRequest(req *http.Request, token *oauth2.Token) ([]byte, error) {
|
||||
// sendRawUserInfoRequest sends the specified user info request and return its raw response body.
|
||||
func (p *BaseProvider) sendRawUserInfoRequest(req *http.Request, token *oauth2.Token) ([]byte, error) {
|
||||
client := p.Client(token)
|
||||
|
||||
res, err := client.Do(req)
|
||||
@@ -167,7 +167,7 @@ func (p *baseProvider) sendRawUserDataRequest(req *http.Request, token *oauth2.T
|
||||
if res.StatusCode >= 400 {
|
||||
return nil, fmt.Errorf(
|
||||
"failed to fetch OAuth2 user profile via %s (%d):\n%s",
|
||||
p.userApiUrl,
|
||||
p.userInfoURL,
|
||||
res.StatusCode,
|
||||
string(result),
|
||||
)
|
||||
@@ -177,15 +177,15 @@ func (p *baseProvider) sendRawUserDataRequest(req *http.Request, token *oauth2.T
|
||||
}
|
||||
|
||||
// oauth2Config constructs a oauth2.Config instance based on the provider settings.
|
||||
func (p *baseProvider) oauth2Config() *oauth2.Config {
|
||||
func (p *BaseProvider) oauth2Config() *oauth2.Config {
|
||||
return &oauth2.Config{
|
||||
RedirectURL: p.redirectUrl,
|
||||
RedirectURL: p.redirectURL,
|
||||
ClientID: p.clientId,
|
||||
ClientSecret: p.clientSecret,
|
||||
Scopes: p.scopes,
|
||||
Endpoint: oauth2.Endpoint{
|
||||
AuthURL: p.authUrl,
|
||||
TokenURL: p.tokenUrl,
|
||||
AuthURL: p.authURL,
|
||||
TokenURL: p.tokenURL,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
)
|
||||
|
||||
func TestContext(t *testing.T) {
|
||||
b := baseProvider{}
|
||||
b := BaseProvider{}
|
||||
|
||||
before := b.Scopes()
|
||||
if before != nil {
|
||||
@@ -24,7 +24,7 @@ func TestContext(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDisplayName(t *testing.T) {
|
||||
b := baseProvider{}
|
||||
b := BaseProvider{}
|
||||
|
||||
before := b.DisplayName()
|
||||
if before != "" {
|
||||
@@ -40,7 +40,7 @@ func TestDisplayName(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPKCE(t *testing.T) {
|
||||
b := baseProvider{}
|
||||
b := BaseProvider{}
|
||||
|
||||
before := b.PKCE()
|
||||
if before != false {
|
||||
@@ -56,7 +56,7 @@ func TestPKCE(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestScopes(t *testing.T) {
|
||||
b := baseProvider{}
|
||||
b := BaseProvider{}
|
||||
|
||||
before := b.Scopes()
|
||||
if len(before) != 0 {
|
||||
@@ -72,7 +72,7 @@ func TestScopes(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestClientId(t *testing.T) {
|
||||
b := baseProvider{}
|
||||
b := BaseProvider{}
|
||||
|
||||
before := b.ClientId()
|
||||
if before != "" {
|
||||
@@ -88,7 +88,7 @@ func TestClientId(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestClientSecret(t *testing.T) {
|
||||
b := baseProvider{}
|
||||
b := BaseProvider{}
|
||||
|
||||
before := b.ClientSecret()
|
||||
if before != "" {
|
||||
@@ -103,82 +103,82 @@ func TestClientSecret(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRedirectUrl(t *testing.T) {
|
||||
b := baseProvider{}
|
||||
func TestRedirectURL(t *testing.T) {
|
||||
b := BaseProvider{}
|
||||
|
||||
before := b.RedirectUrl()
|
||||
before := b.RedirectURL()
|
||||
if before != "" {
|
||||
t.Fatalf("Expected RedirectUrl to be empty, got %v", before)
|
||||
t.Fatalf("Expected RedirectURL to be empty, got %v", before)
|
||||
}
|
||||
|
||||
b.SetRedirectUrl("test")
|
||||
b.SetRedirectURL("test")
|
||||
|
||||
after := b.RedirectUrl()
|
||||
after := b.RedirectURL()
|
||||
if after != "test" {
|
||||
t.Fatalf("Expected RedirectUrl to be 'test', got %v", after)
|
||||
t.Fatalf("Expected RedirectURL to be 'test', got %v", after)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthUrl(t *testing.T) {
|
||||
b := baseProvider{}
|
||||
func TestAuthURL(t *testing.T) {
|
||||
b := BaseProvider{}
|
||||
|
||||
before := b.AuthUrl()
|
||||
before := b.AuthURL()
|
||||
if before != "" {
|
||||
t.Fatalf("Expected authUrl to be empty, got %v", before)
|
||||
t.Fatalf("Expected authURL to be empty, got %v", before)
|
||||
}
|
||||
|
||||
b.SetAuthUrl("test")
|
||||
b.SetAuthURL("test")
|
||||
|
||||
after := b.AuthUrl()
|
||||
after := b.AuthURL()
|
||||
if after != "test" {
|
||||
t.Fatalf("Expected authUrl to be 'test', got %v", after)
|
||||
t.Fatalf("Expected authURL to be 'test', got %v", after)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTokenUrl(t *testing.T) {
|
||||
b := baseProvider{}
|
||||
func TestTokenURL(t *testing.T) {
|
||||
b := BaseProvider{}
|
||||
|
||||
before := b.TokenUrl()
|
||||
before := b.TokenURL()
|
||||
if before != "" {
|
||||
t.Fatalf("Expected tokenUrl to be empty, got %v", before)
|
||||
t.Fatalf("Expected tokenURL to be empty, got %v", before)
|
||||
}
|
||||
|
||||
b.SetTokenUrl("test")
|
||||
b.SetTokenURL("test")
|
||||
|
||||
after := b.TokenUrl()
|
||||
after := b.TokenURL()
|
||||
if after != "test" {
|
||||
t.Fatalf("Expected tokenUrl to be 'test', got %v", after)
|
||||
t.Fatalf("Expected tokenURL to be 'test', got %v", after)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserApiUrl(t *testing.T) {
|
||||
b := baseProvider{}
|
||||
func TestUserInfoURL(t *testing.T) {
|
||||
b := BaseProvider{}
|
||||
|
||||
before := b.UserApiUrl()
|
||||
before := b.UserInfoURL()
|
||||
if before != "" {
|
||||
t.Fatalf("Expected userApiUrl to be empty, got %v", before)
|
||||
t.Fatalf("Expected userInfoURL to be empty, got %v", before)
|
||||
}
|
||||
|
||||
b.SetUserApiUrl("test")
|
||||
b.SetUserInfoURL("test")
|
||||
|
||||
after := b.UserApiUrl()
|
||||
after := b.UserInfoURL()
|
||||
if after != "test" {
|
||||
t.Fatalf("Expected userApiUrl to be 'test', got %v", after)
|
||||
t.Fatalf("Expected userInfoURL to be 'test', got %v", after)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildAuthUrl(t *testing.T) {
|
||||
b := baseProvider{
|
||||
authUrl: "authUrl_test",
|
||||
tokenUrl: "tokenUrl_test",
|
||||
redirectUrl: "redirectUrl_test",
|
||||
func TestBuildAuthURL(t *testing.T) {
|
||||
b := BaseProvider{
|
||||
authURL: "authURL_test",
|
||||
tokenURL: "tokenURL_test",
|
||||
redirectURL: "redirectURL_test",
|
||||
clientId: "clientId_test",
|
||||
clientSecret: "clientSecret_test",
|
||||
scopes: []string{"test_scope"},
|
||||
}
|
||||
|
||||
expected := "authUrl_test?access_type=offline&client_id=clientId_test&prompt=consent&redirect_uri=redirectUrl_test&response_type=code&scope=test_scope&state=state_test"
|
||||
result := b.BuildAuthUrl("state_test", oauth2.AccessTypeOffline, oauth2.ApprovalForce)
|
||||
expected := "authURL_test?access_type=offline&client_id=clientId_test&prompt=consent&redirect_uri=redirectURL_test&response_type=code&scope=test_scope&state=state_test"
|
||||
result := b.BuildAuthURL("state_test", oauth2.AccessTypeOffline, oauth2.ApprovalForce)
|
||||
|
||||
if result != expected {
|
||||
t.Errorf("Expected auth url %q, got %q", expected, result)
|
||||
@@ -186,7 +186,7 @@ func TestBuildAuthUrl(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestClient(t *testing.T) {
|
||||
b := baseProvider{}
|
||||
b := BaseProvider{}
|
||||
|
||||
result := b.Client(&oauth2.Token{})
|
||||
if result == nil {
|
||||
@@ -195,10 +195,10 @@ func TestClient(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestOauth2Config(t *testing.T) {
|
||||
b := baseProvider{
|
||||
authUrl: "authUrl_test",
|
||||
tokenUrl: "tokenUrl_test",
|
||||
redirectUrl: "redirectUrl_test",
|
||||
b := BaseProvider{
|
||||
authURL: "authURL_test",
|
||||
tokenURL: "tokenURL_test",
|
||||
redirectURL: "redirectURL_test",
|
||||
clientId: "clientId_test",
|
||||
clientSecret: "clientSecret_test",
|
||||
scopes: []string{"test"},
|
||||
@@ -206,8 +206,8 @@ func TestOauth2Config(t *testing.T) {
|
||||
|
||||
result := b.oauth2Config()
|
||||
|
||||
if result.RedirectURL != b.RedirectUrl() {
|
||||
t.Errorf("Expected redirectUrl %s, got %s", b.RedirectUrl(), result.RedirectURL)
|
||||
if result.RedirectURL != b.RedirectURL() {
|
||||
t.Errorf("Expected redirectURL %s, got %s", b.RedirectURL(), result.RedirectURL)
|
||||
}
|
||||
|
||||
if result.ClientID != b.ClientId() {
|
||||
@@ -218,12 +218,12 @@ func TestOauth2Config(t *testing.T) {
|
||||
t.Errorf("Expected clientSecret %s, got %s", b.ClientSecret(), result.ClientSecret)
|
||||
}
|
||||
|
||||
if result.Endpoint.AuthURL != b.AuthUrl() {
|
||||
t.Errorf("Expected authUrl %s, got %s", b.AuthUrl(), result.Endpoint.AuthURL)
|
||||
if result.Endpoint.AuthURL != b.AuthURL() {
|
||||
t.Errorf("Expected authURL %s, got %s", b.AuthURL(), result.Endpoint.AuthURL)
|
||||
}
|
||||
|
||||
if result.Endpoint.TokenURL != b.TokenUrl() {
|
||||
t.Errorf("Expected authUrl %s, got %s", b.TokenUrl(), result.Endpoint.TokenURL)
|
||||
if result.Endpoint.TokenURL != b.TokenURL() {
|
||||
t.Errorf("Expected authURL %s, got %s", b.TokenURL(), result.Endpoint.TokenURL)
|
||||
}
|
||||
|
||||
if len(result.Scopes) != len(b.Scopes()) || result.Scopes[0] != b.Scopes()[0] {
|
||||
|
||||
+12
-8
@@ -10,6 +10,10 @@ import (
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Providers[NameBitbucket] = wrapFactory(NewBitbucketProvider)
|
||||
}
|
||||
|
||||
var _ Provider = (*Bitbucket)(nil)
|
||||
|
||||
// NameBitbucket is the unique name of the Bitbucket provider.
|
||||
@@ -17,19 +21,19 @@ const NameBitbucket = "bitbucket"
|
||||
|
||||
// Bitbucket is an auth provider for Bitbucket.
|
||||
type Bitbucket struct {
|
||||
*baseProvider
|
||||
BaseProvider
|
||||
}
|
||||
|
||||
// NewBitbucketProvider creates a new Bitbucket provider instance with some defaults.
|
||||
func NewBitbucketProvider() *Bitbucket {
|
||||
return &Bitbucket{&baseProvider{
|
||||
return &Bitbucket{BaseProvider{
|
||||
ctx: context.Background(),
|
||||
displayName: "Bitbucket",
|
||||
pkce: false,
|
||||
scopes: []string{"account"},
|
||||
authUrl: "https://bitbucket.org/site/oauth2/authorize",
|
||||
tokenUrl: "https://bitbucket.org/site/oauth2/access_token",
|
||||
userApiUrl: "https://api.bitbucket.org/2.0/user",
|
||||
authURL: "https://bitbucket.org/site/oauth2/authorize",
|
||||
tokenURL: "https://bitbucket.org/site/oauth2/access_token",
|
||||
userInfoURL: "https://api.bitbucket.org/2.0/user",
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -37,7 +41,7 @@ func NewBitbucketProvider() *Bitbucket {
|
||||
//
|
||||
// API reference: https://developer.atlassian.com/cloud/bitbucket/rest/api-group-users/#api-user-get
|
||||
func (p *Bitbucket) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
data, err := p.FetchRawUserData(token)
|
||||
data, err := p.FetchRawUserInfo(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -76,7 +80,7 @@ func (p *Bitbucket) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
Name: extracted.DisplayName,
|
||||
Username: extracted.Username,
|
||||
Email: email,
|
||||
AvatarUrl: extracted.Links.Avatar.Href,
|
||||
AvatarURL: extracted.Links.Avatar.Href,
|
||||
RawUser: rawUser,
|
||||
AccessToken: token.AccessToken,
|
||||
RefreshToken: token.RefreshToken,
|
||||
@@ -95,7 +99,7 @@ func (p *Bitbucket) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
//
|
||||
// API reference: https://developer.atlassian.com/cloud/bitbucket/rest/api-group-users/#api-user-emails-get
|
||||
func (p *Bitbucket) fetchPrimaryEmail(token *oauth2.Token) (string, error) {
|
||||
response, err := p.Client(token).Get(p.userApiUrl + "/emails")
|
||||
response, err := p.Client(token).Get(p.userInfoURL + "/emails")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
+12
-8
@@ -9,6 +9,10 @@ import (
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Providers[NameDiscord] = wrapFactory(NewDiscordProvider)
|
||||
}
|
||||
|
||||
var _ Provider = (*Discord)(nil)
|
||||
|
||||
// NameDiscord is the unique name of the Discord provider.
|
||||
@@ -16,21 +20,21 @@ const NameDiscord string = "discord"
|
||||
|
||||
// Discord allows authentication via Discord OAuth2.
|
||||
type Discord struct {
|
||||
*baseProvider
|
||||
BaseProvider
|
||||
}
|
||||
|
||||
// NewDiscordProvider creates a new Discord provider instance with some defaults.
|
||||
func NewDiscordProvider() *Discord {
|
||||
// https://discord.com/developers/docs/topics/oauth2
|
||||
// https://discord.com/developers/docs/resources/user#get-current-user
|
||||
return &Discord{&baseProvider{
|
||||
return &Discord{BaseProvider{
|
||||
ctx: context.Background(),
|
||||
displayName: "Discord",
|
||||
pkce: true,
|
||||
scopes: []string{"identify", "email"},
|
||||
authUrl: "https://discord.com/api/oauth2/authorize",
|
||||
tokenUrl: "https://discord.com/api/oauth2/token",
|
||||
userApiUrl: "https://discord.com/api/users/@me",
|
||||
authURL: "https://discord.com/api/oauth2/authorize",
|
||||
tokenURL: "https://discord.com/api/oauth2/token",
|
||||
userInfoURL: "https://discord.com/api/users/@me",
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -38,7 +42,7 @@ func NewDiscordProvider() *Discord {
|
||||
//
|
||||
// API reference: https://discord.com/developers/docs/resources/user#user-object
|
||||
func (p *Discord) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
data, err := p.FetchRawUserData(token)
|
||||
data, err := p.FetchRawUserInfo(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -62,7 +66,7 @@ func (p *Discord) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
|
||||
// Build a full avatar URL using the avatar hash provided in the API response
|
||||
// https://discord.com/developers/docs/reference#image-formatting
|
||||
avatarUrl := fmt.Sprintf("https://cdn.discordapp.com/avatars/%s/%s.png", extracted.Id, extracted.Avatar)
|
||||
avatarURL := fmt.Sprintf("https://cdn.discordapp.com/avatars/%s/%s.png", extracted.Id, extracted.Avatar)
|
||||
|
||||
// Concatenate the user's username and discriminator into a single username string
|
||||
username := fmt.Sprintf("%s#%s", extracted.Username, extracted.Discriminator)
|
||||
@@ -71,7 +75,7 @@ func (p *Discord) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
Id: extracted.Id,
|
||||
Name: username,
|
||||
Username: extracted.Username,
|
||||
AvatarUrl: avatarUrl,
|
||||
AvatarURL: avatarURL,
|
||||
RawUser: rawUser,
|
||||
AccessToken: token.AccessToken,
|
||||
RefreshToken: token.RefreshToken,
|
||||
|
||||
+11
-7
@@ -9,6 +9,10 @@ import (
|
||||
"golang.org/x/oauth2/facebook"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Providers[NameFacebook] = wrapFactory(NewFacebookProvider)
|
||||
}
|
||||
|
||||
var _ Provider = (*Facebook)(nil)
|
||||
|
||||
// NameFacebook is the unique name of the Facebook provider.
|
||||
@@ -16,19 +20,19 @@ const NameFacebook string = "facebook"
|
||||
|
||||
// Facebook allows authentication via Facebook OAuth2.
|
||||
type Facebook struct {
|
||||
*baseProvider
|
||||
BaseProvider
|
||||
}
|
||||
|
||||
// NewFacebookProvider creates new Facebook provider instance with some defaults.
|
||||
func NewFacebookProvider() *Facebook {
|
||||
return &Facebook{&baseProvider{
|
||||
return &Facebook{BaseProvider{
|
||||
ctx: context.Background(),
|
||||
displayName: "Facebook",
|
||||
pkce: true,
|
||||
scopes: []string{"email"},
|
||||
authUrl: facebook.Endpoint.AuthURL,
|
||||
tokenUrl: facebook.Endpoint.TokenURL,
|
||||
userApiUrl: "https://graph.facebook.com/me?fields=name,email,picture.type(large)",
|
||||
authURL: facebook.Endpoint.AuthURL,
|
||||
tokenURL: facebook.Endpoint.TokenURL,
|
||||
userInfoURL: "https://graph.facebook.com/me?fields=name,email,picture.type(large)",
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -36,7 +40,7 @@ func NewFacebookProvider() *Facebook {
|
||||
//
|
||||
// API reference: https://developers.facebook.com/docs/graph-api/reference/user/
|
||||
func (p *Facebook) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
data, err := p.FetchRawUserData(token)
|
||||
data, err := p.FetchRawUserInfo(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -62,7 +66,7 @@ func (p *Facebook) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
Id: extracted.Id,
|
||||
Name: extracted.Name,
|
||||
Email: extracted.Email,
|
||||
AvatarUrl: extracted.Picture.Data.Url,
|
||||
AvatarURL: extracted.Picture.Data.Url,
|
||||
RawUser: rawUser,
|
||||
AccessToken: token.AccessToken,
|
||||
RefreshToken: token.RefreshToken,
|
||||
|
||||
+12
-8
@@ -9,6 +9,10 @@ import (
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Providers[NameGitea] = wrapFactory(NewGiteaProvider)
|
||||
}
|
||||
|
||||
var _ Provider = (*Gitea)(nil)
|
||||
|
||||
// NameGitea is the unique name of the Gitea provider.
|
||||
@@ -16,19 +20,19 @@ const NameGitea string = "gitea"
|
||||
|
||||
// Gitea allows authentication via Gitea OAuth2.
|
||||
type Gitea struct {
|
||||
*baseProvider
|
||||
BaseProvider
|
||||
}
|
||||
|
||||
// NewGiteaProvider creates new Gitea provider instance with some defaults.
|
||||
func NewGiteaProvider() *Gitea {
|
||||
return &Gitea{&baseProvider{
|
||||
return &Gitea{BaseProvider{
|
||||
ctx: context.Background(),
|
||||
displayName: "Gitea",
|
||||
pkce: true,
|
||||
scopes: []string{"read:user", "user:email"},
|
||||
authUrl: "https://gitea.com/login/oauth/authorize",
|
||||
tokenUrl: "https://gitea.com/login/oauth/access_token",
|
||||
userApiUrl: "https://gitea.com/api/v1/user",
|
||||
authURL: "https://gitea.com/login/oauth/authorize",
|
||||
tokenURL: "https://gitea.com/login/oauth/access_token",
|
||||
userInfoURL: "https://gitea.com/api/v1/user",
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -36,7 +40,7 @@ func NewGiteaProvider() *Gitea {
|
||||
//
|
||||
// API reference: https://try.gitea.io/api/swagger#/user/userGetCurrent
|
||||
func (p *Gitea) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
data, err := p.FetchRawUserData(token)
|
||||
data, err := p.FetchRawUserInfo(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -51,7 +55,7 @@ func (p *Gitea) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
Name string `json:"full_name"`
|
||||
Username string `json:"login"`
|
||||
Email string `json:"email"`
|
||||
AvatarUrl string `json:"avatar_url"`
|
||||
AvatarURL string `json:"avatar_url"`
|
||||
}{}
|
||||
if err := json.Unmarshal(data, &extracted); err != nil {
|
||||
return nil, err
|
||||
@@ -62,7 +66,7 @@ func (p *Gitea) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
Name: extracted.Name,
|
||||
Username: extracted.Username,
|
||||
Email: extracted.Email,
|
||||
AvatarUrl: extracted.AvatarUrl,
|
||||
AvatarURL: extracted.AvatarURL,
|
||||
RawUser: rawUser,
|
||||
AccessToken: token.AccessToken,
|
||||
RefreshToken: token.RefreshToken,
|
||||
|
||||
+12
-8
@@ -11,6 +11,10 @@ import (
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Providers[NameGitee] = wrapFactory(NewGiteeProvider)
|
||||
}
|
||||
|
||||
var _ Provider = (*Gitee)(nil)
|
||||
|
||||
// NameGitee is the unique name of the Gitee provider.
|
||||
@@ -18,19 +22,19 @@ const NameGitee string = "gitee"
|
||||
|
||||
// Gitee allows authentication via Gitee OAuth2.
|
||||
type Gitee struct {
|
||||
*baseProvider
|
||||
BaseProvider
|
||||
}
|
||||
|
||||
// NewGiteeProvider creates new Gitee provider instance with some defaults.
|
||||
func NewGiteeProvider() *Gitee {
|
||||
return &Gitee{&baseProvider{
|
||||
return &Gitee{BaseProvider{
|
||||
ctx: context.Background(),
|
||||
displayName: "Gitee",
|
||||
pkce: true,
|
||||
scopes: []string{"user_info", "emails"},
|
||||
authUrl: "https://gitee.com/oauth/authorize",
|
||||
tokenUrl: "https://gitee.com/oauth/token",
|
||||
userApiUrl: "https://gitee.com/api/v5/user",
|
||||
authURL: "https://gitee.com/oauth/authorize",
|
||||
tokenURL: "https://gitee.com/oauth/token",
|
||||
userInfoURL: "https://gitee.com/api/v5/user",
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -38,7 +42,7 @@ func NewGiteeProvider() *Gitee {
|
||||
//
|
||||
// API reference: https://gitee.com/api/v5/swagger#/getV5User
|
||||
func (p *Gitee) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
data, err := p.FetchRawUserData(token)
|
||||
data, err := p.FetchRawUserInfo(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -53,7 +57,7 @@ func (p *Gitee) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
AvatarUrl string `json:"avatar_url"`
|
||||
AvatarURL string `json:"avatar_url"`
|
||||
}{}
|
||||
if err := json.Unmarshal(data, &extracted); err != nil {
|
||||
return nil, err
|
||||
@@ -63,7 +67,7 @@ func (p *Gitee) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
Id: strconv.Itoa(extracted.Id),
|
||||
Name: extracted.Name,
|
||||
Username: extracted.Login,
|
||||
AvatarUrl: extracted.AvatarUrl,
|
||||
AvatarURL: extracted.AvatarURL,
|
||||
RawUser: rawUser,
|
||||
AccessToken: token.AccessToken,
|
||||
RefreshToken: token.RefreshToken,
|
||||
|
||||
+13
-9
@@ -11,6 +11,10 @@ import (
|
||||
"golang.org/x/oauth2/github"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Providers[NameGithub] = wrapFactory(NewGithubProvider)
|
||||
}
|
||||
|
||||
var _ Provider = (*Github)(nil)
|
||||
|
||||
// NameGithub is the unique name of the Github provider.
|
||||
@@ -18,19 +22,19 @@ const NameGithub string = "github"
|
||||
|
||||
// Github allows authentication via Github OAuth2.
|
||||
type Github struct {
|
||||
*baseProvider
|
||||
BaseProvider
|
||||
}
|
||||
|
||||
// NewGithubProvider creates new Github provider instance with some defaults.
|
||||
func NewGithubProvider() *Github {
|
||||
return &Github{&baseProvider{
|
||||
return &Github{BaseProvider{
|
||||
ctx: context.Background(),
|
||||
displayName: "GitHub",
|
||||
pkce: true, // technically is not supported yet but it is safe as the PKCE params are just ignored
|
||||
scopes: []string{"read:user", "user:email"},
|
||||
authUrl: github.Endpoint.AuthURL,
|
||||
tokenUrl: github.Endpoint.TokenURL,
|
||||
userApiUrl: "https://api.github.com/user",
|
||||
authURL: github.Endpoint.AuthURL,
|
||||
tokenURL: github.Endpoint.TokenURL,
|
||||
userInfoURL: "https://api.github.com/user",
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -38,7 +42,7 @@ func NewGithubProvider() *Github {
|
||||
//
|
||||
// API reference: https://docs.github.com/en/rest/reference/users#get-the-authenticated-user
|
||||
func (p *Github) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
data, err := p.FetchRawUserData(token)
|
||||
data, err := p.FetchRawUserInfo(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -53,7 +57,7 @@ func (p *Github) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
AvatarUrl string `json:"avatar_url"`
|
||||
AvatarURL string `json:"avatar_url"`
|
||||
}{}
|
||||
if err := json.Unmarshal(data, &extracted); err != nil {
|
||||
return nil, err
|
||||
@@ -64,7 +68,7 @@ func (p *Github) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
Name: extracted.Name,
|
||||
Username: extracted.Login,
|
||||
Email: extracted.Email,
|
||||
AvatarUrl: extracted.AvatarUrl,
|
||||
AvatarURL: extracted.AvatarURL,
|
||||
RawUser: rawUser,
|
||||
AccessToken: token.AccessToken,
|
||||
RefreshToken: token.RefreshToken,
|
||||
@@ -95,7 +99,7 @@ func (p *Github) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
func (p *Github) fetchPrimaryEmail(token *oauth2.Token) (string, error) {
|
||||
client := p.Client(token)
|
||||
|
||||
response, err := client.Get(p.userApiUrl + "/emails")
|
||||
response, err := client.Get(p.userInfoURL + "/emails")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
+12
-8
@@ -9,6 +9,10 @@ import (
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Providers[NameGitlab] = wrapFactory(NewGitlabProvider)
|
||||
}
|
||||
|
||||
var _ Provider = (*Gitlab)(nil)
|
||||
|
||||
// NameGitlab is the unique name of the Gitlab provider.
|
||||
@@ -16,19 +20,19 @@ const NameGitlab string = "gitlab"
|
||||
|
||||
// Gitlab allows authentication via Gitlab OAuth2.
|
||||
type Gitlab struct {
|
||||
*baseProvider
|
||||
BaseProvider
|
||||
}
|
||||
|
||||
// NewGitlabProvider creates new Gitlab provider instance with some defaults.
|
||||
func NewGitlabProvider() *Gitlab {
|
||||
return &Gitlab{&baseProvider{
|
||||
return &Gitlab{BaseProvider{
|
||||
ctx: context.Background(),
|
||||
displayName: "GitLab",
|
||||
pkce: true,
|
||||
scopes: []string{"read_user"},
|
||||
authUrl: "https://gitlab.com/oauth/authorize",
|
||||
tokenUrl: "https://gitlab.com/oauth/token",
|
||||
userApiUrl: "https://gitlab.com/api/v4/user",
|
||||
authURL: "https://gitlab.com/oauth/authorize",
|
||||
tokenURL: "https://gitlab.com/oauth/token",
|
||||
userInfoURL: "https://gitlab.com/api/v4/user",
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -36,7 +40,7 @@ func NewGitlabProvider() *Gitlab {
|
||||
//
|
||||
// API reference: https://docs.gitlab.com/ee/api/users.html#for-admin
|
||||
func (p *Gitlab) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
data, err := p.FetchRawUserData(token)
|
||||
data, err := p.FetchRawUserInfo(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -51,7 +55,7 @@ func (p *Gitlab) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
Name string `json:"name"`
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
AvatarUrl string `json:"avatar_url"`
|
||||
AvatarURL string `json:"avatar_url"`
|
||||
}{}
|
||||
if err := json.Unmarshal(data, &extracted); err != nil {
|
||||
return nil, err
|
||||
@@ -62,7 +66,7 @@ func (p *Gitlab) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
Name: extracted.Name,
|
||||
Username: extracted.Username,
|
||||
Email: extracted.Email,
|
||||
AvatarUrl: extracted.AvatarUrl,
|
||||
AvatarURL: extracted.AvatarURL,
|
||||
RawUser: rawUser,
|
||||
AccessToken: token.AccessToken,
|
||||
RefreshToken: token.RefreshToken,
|
||||
|
||||
+11
-7
@@ -8,6 +8,10 @@ import (
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Providers[NameGoogle] = wrapFactory(NewGoogleProvider)
|
||||
}
|
||||
|
||||
var _ Provider = (*Google)(nil)
|
||||
|
||||
// NameGoogle is the unique name of the Google provider.
|
||||
@@ -15,12 +19,12 @@ const NameGoogle string = "google"
|
||||
|
||||
// Google allows authentication via Google OAuth2.
|
||||
type Google struct {
|
||||
*baseProvider
|
||||
BaseProvider
|
||||
}
|
||||
|
||||
// NewGoogleProvider creates new Google provider instance with some defaults.
|
||||
func NewGoogleProvider() *Google {
|
||||
return &Google{&baseProvider{
|
||||
return &Google{BaseProvider{
|
||||
ctx: context.Background(),
|
||||
displayName: "Google",
|
||||
pkce: true,
|
||||
@@ -28,15 +32,15 @@ func NewGoogleProvider() *Google {
|
||||
"https://www.googleapis.com/auth/userinfo.profile",
|
||||
"https://www.googleapis.com/auth/userinfo.email",
|
||||
},
|
||||
authUrl: "https://accounts.google.com/o/oauth2/auth",
|
||||
tokenUrl: "https://accounts.google.com/o/oauth2/token",
|
||||
userApiUrl: "https://www.googleapis.com/oauth2/v1/userinfo",
|
||||
authURL: "https://accounts.google.com/o/oauth2/auth",
|
||||
tokenURL: "https://accounts.google.com/o/oauth2/token",
|
||||
userInfoURL: "https://www.googleapis.com/oauth2/v1/userinfo",
|
||||
}}
|
||||
}
|
||||
|
||||
// FetchAuthUser returns an AuthUser instance based the Google's user api.
|
||||
func (p *Google) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
data, err := p.FetchRawUserData(token)
|
||||
data, err := p.FetchRawUserInfo(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -60,7 +64,7 @@ func (p *Google) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
user := &AuthUser{
|
||||
Id: extracted.Id,
|
||||
Name: extracted.Name,
|
||||
AvatarUrl: extracted.Picture,
|
||||
AvatarURL: extracted.Picture,
|
||||
RawUser: rawUser,
|
||||
AccessToken: token.AccessToken,
|
||||
RefreshToken: token.RefreshToken,
|
||||
|
||||
+10
-6
@@ -9,6 +9,10 @@ import (
|
||||
"golang.org/x/oauth2/instagram"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Providers[NameInstagram] = wrapFactory(NewInstagramProvider)
|
||||
}
|
||||
|
||||
var _ Provider = (*Instagram)(nil)
|
||||
|
||||
// NameInstagram is the unique name of the Instagram provider.
|
||||
@@ -16,19 +20,19 @@ const NameInstagram string = "instagram"
|
||||
|
||||
// Instagram allows authentication via Instagram OAuth2.
|
||||
type Instagram struct {
|
||||
*baseProvider
|
||||
BaseProvider
|
||||
}
|
||||
|
||||
// NewInstagramProvider creates new Instagram provider instance with some defaults.
|
||||
func NewInstagramProvider() *Instagram {
|
||||
return &Instagram{&baseProvider{
|
||||
return &Instagram{BaseProvider{
|
||||
ctx: context.Background(),
|
||||
displayName: "Instagram",
|
||||
pkce: true,
|
||||
scopes: []string{"user_profile"},
|
||||
authUrl: instagram.Endpoint.AuthURL,
|
||||
tokenUrl: instagram.Endpoint.TokenURL,
|
||||
userApiUrl: "https://graph.instagram.com/me?fields=id,username,account_type",
|
||||
authURL: instagram.Endpoint.AuthURL,
|
||||
tokenURL: instagram.Endpoint.TokenURL,
|
||||
userInfoURL: "https://graph.instagram.com/me?fields=id,username,account_type",
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -36,7 +40,7 @@ func NewInstagramProvider() *Instagram {
|
||||
//
|
||||
// API reference: https://developers.facebook.com/docs/instagram-basic-display-api/reference/user#fields
|
||||
func (p *Instagram) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
data, err := p.FetchRawUserData(token)
|
||||
data, err := p.FetchRawUserInfo(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+12
-8
@@ -10,6 +10,10 @@ import (
|
||||
"golang.org/x/oauth2/kakao"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Providers[NameKakao] = wrapFactory(NewKakaoProvider)
|
||||
}
|
||||
|
||||
var _ Provider = (*Kakao)(nil)
|
||||
|
||||
// NameKakao is the unique name of the Kakao provider.
|
||||
@@ -17,19 +21,19 @@ const NameKakao string = "kakao"
|
||||
|
||||
// Kakao allows authentication via Kakao OAuth2.
|
||||
type Kakao struct {
|
||||
*baseProvider
|
||||
BaseProvider
|
||||
}
|
||||
|
||||
// NewKakaoProvider creates a new Kakao provider instance with some defaults.
|
||||
func NewKakaoProvider() *Kakao {
|
||||
return &Kakao{&baseProvider{
|
||||
return &Kakao{BaseProvider{
|
||||
ctx: context.Background(),
|
||||
displayName: "Kakao",
|
||||
pkce: true,
|
||||
scopes: []string{"account_email", "profile_nickname", "profile_image"},
|
||||
authUrl: kakao.Endpoint.AuthURL,
|
||||
tokenUrl: kakao.Endpoint.TokenURL,
|
||||
userApiUrl: "https://kapi.kakao.com/v2/user/me",
|
||||
authURL: kakao.Endpoint.AuthURL,
|
||||
tokenURL: kakao.Endpoint.TokenURL,
|
||||
userInfoURL: "https://kapi.kakao.com/v2/user/me",
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -37,7 +41,7 @@ func NewKakaoProvider() *Kakao {
|
||||
//
|
||||
// API reference: https://developers.kakao.com/docs/latest/en/kakaologin/rest-api#req-user-info-response
|
||||
func (p *Kakao) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
data, err := p.FetchRawUserData(token)
|
||||
data, err := p.FetchRawUserInfo(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -51,7 +55,7 @@ func (p *Kakao) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
Id int `json:"id"`
|
||||
Profile struct {
|
||||
Nickname string `json:"nickname"`
|
||||
ImageUrl string `json:"profile_image"`
|
||||
ImageURL string `json:"profile_image"`
|
||||
} `json:"properties"`
|
||||
KakaoAccount struct {
|
||||
Email string `json:"email"`
|
||||
@@ -66,7 +70,7 @@ func (p *Kakao) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
user := &AuthUser{
|
||||
Id: strconv.Itoa(extracted.Id),
|
||||
Username: extracted.Profile.Nickname,
|
||||
AvatarUrl: extracted.Profile.ImageUrl,
|
||||
AvatarURL: extracted.Profile.ImageURL,
|
||||
RawUser: rawUser,
|
||||
AccessToken: token.AccessToken,
|
||||
RefreshToken: token.RefreshToken,
|
||||
|
||||
+12
-8
@@ -8,6 +8,10 @@ import (
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Providers[NameLivechat] = wrapFactory(NewLivechatProvider)
|
||||
}
|
||||
|
||||
var _ Provider = (*Livechat)(nil)
|
||||
|
||||
// NameLivechat is the unique name of the Livechat provider.
|
||||
@@ -15,19 +19,19 @@ const NameLivechat = "livechat"
|
||||
|
||||
// Livechat allows authentication via Livechat OAuth2.
|
||||
type Livechat struct {
|
||||
*baseProvider
|
||||
BaseProvider
|
||||
}
|
||||
|
||||
// NewLivechatProvider creates new Livechat provider instance with some defaults.
|
||||
func NewLivechatProvider() *Livechat {
|
||||
return &Livechat{&baseProvider{
|
||||
return &Livechat{BaseProvider{
|
||||
ctx: context.Background(),
|
||||
displayName: "LiveChat",
|
||||
pkce: true,
|
||||
scopes: []string{}, // default scopes are specified from the provider dashboard
|
||||
authUrl: "https://accounts.livechat.com/",
|
||||
tokenUrl: "https://accounts.livechat.com/token",
|
||||
userApiUrl: "https://accounts.livechat.com/v2/accounts/me",
|
||||
authURL: "https://accounts.livechat.com/",
|
||||
tokenURL: "https://accounts.livechat.com/token",
|
||||
userInfoURL: "https://accounts.livechat.com/v2/accounts/me",
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -35,7 +39,7 @@ func NewLivechatProvider() *Livechat {
|
||||
//
|
||||
// API reference: https://developers.livechat.com/docs/authorization
|
||||
func (p *Livechat) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
data, err := p.FetchRawUserData(token)
|
||||
data, err := p.FetchRawUserInfo(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -50,7 +54,7 @@ func (p *Livechat) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
EmailVerified bool `json:"email_verified"`
|
||||
AvatarUrl string `json:"avatar_url"`
|
||||
AvatarURL string `json:"avatar_url"`
|
||||
}{}
|
||||
if err := json.Unmarshal(data, &extracted); err != nil {
|
||||
return nil, err
|
||||
@@ -59,7 +63,7 @@ func (p *Livechat) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
user := &AuthUser{
|
||||
Id: extracted.Id,
|
||||
Name: extracted.Name,
|
||||
AvatarUrl: extracted.AvatarUrl,
|
||||
AvatarURL: extracted.AvatarURL,
|
||||
RawUser: rawUser,
|
||||
AccessToken: token.AccessToken,
|
||||
RefreshToken: token.RefreshToken,
|
||||
|
||||
@@ -10,6 +10,10 @@ import (
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Providers[NameMailcow] = wrapFactory(NewMailcowProvider)
|
||||
}
|
||||
|
||||
var _ Provider = (*Mailcow)(nil)
|
||||
|
||||
// NameMailcow is the unique name of the mailcow provider.
|
||||
@@ -17,12 +21,12 @@ const NameMailcow string = "mailcow"
|
||||
|
||||
// Mailcow allows authentication via mailcow OAuth2.
|
||||
type Mailcow struct {
|
||||
*baseProvider
|
||||
BaseProvider
|
||||
}
|
||||
|
||||
// NewMailcowProvider creates a new mailcow provider instance with some defaults.
|
||||
func NewMailcowProvider() *Mailcow {
|
||||
return &Mailcow{&baseProvider{
|
||||
return &Mailcow{BaseProvider{
|
||||
ctx: context.Background(),
|
||||
displayName: "mailcow",
|
||||
pkce: true,
|
||||
@@ -34,7 +38,7 @@ func NewMailcowProvider() *Mailcow {
|
||||
//
|
||||
// API reference: https://github.com/mailcow/mailcow-dockerized/blob/master/data/web/oauth/profile.php
|
||||
func (p *Mailcow) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
data, err := p.FetchRawUserData(token)
|
||||
data, err := p.FetchRawUserInfo(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+10
-6
@@ -9,6 +9,10 @@ import (
|
||||
"golang.org/x/oauth2/microsoft"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Providers[NameMicrosoft] = wrapFactory(NewMicrosoftProvider)
|
||||
}
|
||||
|
||||
var _ Provider = (*Microsoft)(nil)
|
||||
|
||||
// NameMicrosoft is the unique name of the Microsoft provider.
|
||||
@@ -16,20 +20,20 @@ const NameMicrosoft string = "microsoft"
|
||||
|
||||
// Microsoft allows authentication via AzureADEndpoint OAuth2.
|
||||
type Microsoft struct {
|
||||
*baseProvider
|
||||
BaseProvider
|
||||
}
|
||||
|
||||
// NewMicrosoftProvider creates new Microsoft AD provider instance with some defaults.
|
||||
func NewMicrosoftProvider() *Microsoft {
|
||||
endpoints := microsoft.AzureADEndpoint("")
|
||||
return &Microsoft{&baseProvider{
|
||||
return &Microsoft{BaseProvider{
|
||||
ctx: context.Background(),
|
||||
displayName: "Microsoft",
|
||||
pkce: true,
|
||||
scopes: []string{"User.Read"},
|
||||
authUrl: endpoints.AuthURL,
|
||||
tokenUrl: endpoints.TokenURL,
|
||||
userApiUrl: "https://graph.microsoft.com/v1.0/me",
|
||||
authURL: endpoints.AuthURL,
|
||||
tokenURL: endpoints.TokenURL,
|
||||
userInfoURL: "https://graph.microsoft.com/v1.0/me",
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -38,7 +42,7 @@ func NewMicrosoftProvider() *Microsoft {
|
||||
// API reference: https://learn.microsoft.com/en-us/azure/active-directory/develop/userinfo
|
||||
// Graph explorer: https://developer.microsoft.com/en-us/graph/graph-explorer
|
||||
func (p *Microsoft) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
data, err := p.FetchRawUserData(token)
|
||||
data, err := p.FetchRawUserInfo(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+12
-4
@@ -8,6 +8,12 @@ import (
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Providers[NameOIDC] = wrapFactory(NewOIDCProvider)
|
||||
Providers[NameOIDC+"2"] = wrapFactory(NewOIDCProvider)
|
||||
Providers[NameOIDC+"3"] = wrapFactory(NewOIDCProvider)
|
||||
}
|
||||
|
||||
var _ Provider = (*OIDC)(nil)
|
||||
|
||||
// NameOIDC is the unique name of the OpenID Connect (OIDC) provider.
|
||||
@@ -15,12 +21,12 @@ const NameOIDC string = "oidc"
|
||||
|
||||
// OIDC allows authentication via OpenID Connect (OIDC) OAuth2 provider.
|
||||
type OIDC struct {
|
||||
*baseProvider
|
||||
BaseProvider
|
||||
}
|
||||
|
||||
// NewOIDCProvider creates new OpenID Connect (OIDC) provider instance with some defaults.
|
||||
func NewOIDCProvider() *OIDC {
|
||||
return &OIDC{&baseProvider{
|
||||
return &OIDC{BaseProvider{
|
||||
ctx: context.Background(),
|
||||
displayName: "OIDC",
|
||||
pkce: true,
|
||||
@@ -35,8 +41,10 @@ func NewOIDCProvider() *OIDC {
|
||||
// FetchAuthUser returns an AuthUser instance based the provider's user api.
|
||||
//
|
||||
// API reference: https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims
|
||||
//
|
||||
// @todo consider adding support for reading the user data from the id_token.
|
||||
func (p *OIDC) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
data, err := p.FetchRawUserData(token)
|
||||
data, err := p.FetchRawUserInfo(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -62,7 +70,7 @@ func (p *OIDC) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
Id: extracted.Id,
|
||||
Name: extracted.Name,
|
||||
Username: extracted.Username,
|
||||
AvatarUrl: extracted.Picture,
|
||||
AvatarURL: extracted.Picture,
|
||||
RawUser: rawUser,
|
||||
AccessToken: token.AccessToken,
|
||||
RefreshToken: token.RefreshToken,
|
||||
|
||||
+12
-8
@@ -8,6 +8,10 @@ import (
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Providers[NamePatreon] = wrapFactory(NewPatreonProvider)
|
||||
}
|
||||
|
||||
var _ Provider = (*Patreon)(nil)
|
||||
|
||||
// NamePatreon is the unique name of the Patreon provider.
|
||||
@@ -15,19 +19,19 @@ const NamePatreon string = "patreon"
|
||||
|
||||
// Patreon allows authentication via Patreon OAuth2.
|
||||
type Patreon struct {
|
||||
*baseProvider
|
||||
BaseProvider
|
||||
}
|
||||
|
||||
// NewPatreonProvider creates new Patreon provider instance with some defaults.
|
||||
func NewPatreonProvider() *Patreon {
|
||||
return &Patreon{&baseProvider{
|
||||
return &Patreon{BaseProvider{
|
||||
ctx: context.Background(),
|
||||
displayName: "Patreon",
|
||||
pkce: true,
|
||||
scopes: []string{"identity", "identity[email]"},
|
||||
authUrl: "https://www.patreon.com/oauth2/authorize",
|
||||
tokenUrl: "https://www.patreon.com/api/oauth2/token",
|
||||
userApiUrl: "https://www.patreon.com/api/oauth2/v2/identity?fields%5Buser%5D=full_name,email,vanity,image_url,is_email_verified",
|
||||
authURL: "https://www.patreon.com/oauth2/authorize",
|
||||
tokenURL: "https://www.patreon.com/api/oauth2/token",
|
||||
userInfoURL: "https://www.patreon.com/api/oauth2/v2/identity?fields%5Buser%5D=full_name,email,vanity,image_url,is_email_verified",
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -37,7 +41,7 @@ func NewPatreonProvider() *Patreon {
|
||||
// https://docs.patreon.com/#get-api-oauth2-v2-identity
|
||||
// https://docs.patreon.com/#user-v2
|
||||
func (p *Patreon) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
data, err := p.FetchRawUserData(token)
|
||||
data, err := p.FetchRawUserInfo(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -54,7 +58,7 @@ func (p *Patreon) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
Email string `json:"email"`
|
||||
Name string `json:"full_name"`
|
||||
Username string `json:"vanity"`
|
||||
AvatarUrl string `json:"image_url"`
|
||||
AvatarURL string `json:"image_url"`
|
||||
IsEmailVerified bool `json:"is_email_verified"`
|
||||
} `json:"attributes"`
|
||||
} `json:"data"`
|
||||
@@ -67,7 +71,7 @@ func (p *Patreon) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
Id: extracted.Data.Id,
|
||||
Username: extracted.Data.Attributes.Username,
|
||||
Name: extracted.Data.Attributes.Name,
|
||||
AvatarUrl: extracted.Data.Attributes.AvatarUrl,
|
||||
AvatarURL: extracted.Data.Attributes.AvatarURL,
|
||||
RawUser: rawUser,
|
||||
AccessToken: token.AccessToken,
|
||||
RefreshToken: token.RefreshToken,
|
||||
|
||||
@@ -9,6 +9,10 @@ import (
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Providers[NamePlanningcenter] = wrapFactory(NewPlanningcenterProvider)
|
||||
}
|
||||
|
||||
var _ Provider = (*Planningcenter)(nil)
|
||||
|
||||
// NamePlanningcenter is the unique name of the Planningcenter provider.
|
||||
@@ -16,19 +20,19 @@ const NamePlanningcenter string = "planningcenter"
|
||||
|
||||
// Planningcenter allows authentication via Planningcenter OAuth2.
|
||||
type Planningcenter struct {
|
||||
*baseProvider
|
||||
BaseProvider
|
||||
}
|
||||
|
||||
// NewPlanningcenterProvider creates a new Planningcenter provider instance with some defaults.
|
||||
func NewPlanningcenterProvider() *Planningcenter {
|
||||
return &Planningcenter{&baseProvider{
|
||||
return &Planningcenter{BaseProvider{
|
||||
ctx: context.Background(),
|
||||
displayName: "Planning Center",
|
||||
pkce: true,
|
||||
scopes: []string{"people"},
|
||||
authUrl: "https://api.planningcenteronline.com/oauth/authorize",
|
||||
tokenUrl: "https://api.planningcenteronline.com/oauth/token",
|
||||
userApiUrl: "https://api.planningcenteronline.com/people/v2/me",
|
||||
authURL: "https://api.planningcenteronline.com/oauth/authorize",
|
||||
tokenURL: "https://api.planningcenteronline.com/oauth/token",
|
||||
userInfoURL: "https://api.planningcenteronline.com/people/v2/me",
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -36,7 +40,7 @@ func NewPlanningcenterProvider() *Planningcenter {
|
||||
//
|
||||
// API reference: https://developer.planning.center/docs/#/overview/authentication
|
||||
func (p *Planningcenter) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
data, err := p.FetchRawUserData(token)
|
||||
data, err := p.FetchRawUserInfo(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -52,7 +56,7 @@ func (p *Planningcenter) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
Attributes struct {
|
||||
Status string `json:"status"`
|
||||
Name string `json:"name"`
|
||||
AvatarUrl string `json:"avatar"`
|
||||
AvatarURL string `json:"avatar"`
|
||||
// don't map the email because users can have multiple assigned
|
||||
// and it's not clear if they are verified
|
||||
}
|
||||
@@ -69,7 +73,7 @@ func (p *Planningcenter) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
user := &AuthUser{
|
||||
Id: extracted.Data.Id,
|
||||
Name: extracted.Data.Attributes.Name,
|
||||
AvatarUrl: extracted.Data.Attributes.AvatarUrl,
|
||||
AvatarURL: extracted.Data.Attributes.AvatarURL,
|
||||
RawUser: rawUser,
|
||||
AccessToken: token.AccessToken,
|
||||
RefreshToken: token.RefreshToken,
|
||||
|
||||
+12
-8
@@ -9,6 +9,10 @@ import (
|
||||
"golang.org/x/oauth2/spotify"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Providers[NameSpotify] = wrapFactory(NewSpotifyProvider)
|
||||
}
|
||||
|
||||
var _ Provider = (*Spotify)(nil)
|
||||
|
||||
// NameSpotify is the unique name of the Spotify provider.
|
||||
@@ -16,12 +20,12 @@ const NameSpotify string = "spotify"
|
||||
|
||||
// Spotify allows authentication via Spotify OAuth2.
|
||||
type Spotify struct {
|
||||
*baseProvider
|
||||
BaseProvider
|
||||
}
|
||||
|
||||
// NewSpotifyProvider creates a new Spotify provider instance with some defaults.
|
||||
func NewSpotifyProvider() *Spotify {
|
||||
return &Spotify{&baseProvider{
|
||||
return &Spotify{BaseProvider{
|
||||
ctx: context.Background(),
|
||||
displayName: "Spotify",
|
||||
pkce: true,
|
||||
@@ -30,9 +34,9 @@ func NewSpotifyProvider() *Spotify {
|
||||
// currently Spotify doesn't return information whether the email is verified or not
|
||||
// "user-read-email",
|
||||
},
|
||||
authUrl: spotify.Endpoint.AuthURL,
|
||||
tokenUrl: spotify.Endpoint.TokenURL,
|
||||
userApiUrl: "https://api.spotify.com/v1/me",
|
||||
authURL: spotify.Endpoint.AuthURL,
|
||||
tokenURL: spotify.Endpoint.TokenURL,
|
||||
userInfoURL: "https://api.spotify.com/v1/me",
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -40,7 +44,7 @@ func NewSpotifyProvider() *Spotify {
|
||||
//
|
||||
// API reference: https://developer.spotify.com/documentation/web-api/reference/#/operations/get-current-users-profile
|
||||
func (p *Spotify) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
data, err := p.FetchRawUserData(token)
|
||||
data, err := p.FetchRawUserInfo(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -54,7 +58,7 @@ func (p *Spotify) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"display_name"`
|
||||
Images []struct {
|
||||
Url string `json:"url"`
|
||||
URL string `json:"url"`
|
||||
} `json:"images"`
|
||||
// don't map the email because per the official docs
|
||||
// the email field is "unverified" and there is no proof
|
||||
@@ -76,7 +80,7 @@ func (p *Spotify) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
user.Expiry, _ = types.ParseDateTime(token.Expiry)
|
||||
|
||||
if len(extracted.Images) > 0 {
|
||||
user.AvatarUrl = extracted.Images[0].Url
|
||||
user.AvatarURL = extracted.Images[0].URL
|
||||
}
|
||||
|
||||
return user, nil
|
||||
|
||||
+12
-8
@@ -9,6 +9,10 @@ import (
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Providers[NameStrava] = wrapFactory(NewStravaProvider)
|
||||
}
|
||||
|
||||
var _ Provider = (*Strava)(nil)
|
||||
|
||||
// NameStrava is the unique name of the Strava provider.
|
||||
@@ -16,21 +20,21 @@ const NameStrava string = "strava"
|
||||
|
||||
// Strava allows authentication via Strava OAuth2.
|
||||
type Strava struct {
|
||||
*baseProvider
|
||||
BaseProvider
|
||||
}
|
||||
|
||||
// NewStravaProvider creates new Strava provider instance with some defaults.
|
||||
func NewStravaProvider() *Strava {
|
||||
return &Strava{&baseProvider{
|
||||
return &Strava{BaseProvider{
|
||||
ctx: context.Background(),
|
||||
displayName: "Strava",
|
||||
pkce: true,
|
||||
scopes: []string{
|
||||
"profile:read_all",
|
||||
},
|
||||
authUrl: "https://www.strava.com/oauth/authorize",
|
||||
tokenUrl: "https://www.strava.com/api/v3/oauth/token",
|
||||
userApiUrl: "https://www.strava.com/api/v3/athlete",
|
||||
authURL: "https://www.strava.com/oauth/authorize",
|
||||
tokenURL: "https://www.strava.com/api/v3/oauth/token",
|
||||
userInfoURL: "https://www.strava.com/api/v3/athlete",
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -38,7 +42,7 @@ func NewStravaProvider() *Strava {
|
||||
//
|
||||
// API reference: https://developers.strava.com/docs/authentication/
|
||||
func (p *Strava) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
data, err := p.FetchRawUserData(token)
|
||||
data, err := p.FetchRawUserInfo(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -53,7 +57,7 @@ func (p *Strava) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
FirstName string `json:"firstname"`
|
||||
LastName string `json:"lastname"`
|
||||
Username string `json:"username"`
|
||||
ProfileImageUrl string `json:"profile"`
|
||||
ProfileImageURL string `json:"profile"`
|
||||
|
||||
// At the time of writing, Strava OAuth2 doesn't support returning the user email address
|
||||
// Email string `json:"email"`
|
||||
@@ -65,7 +69,7 @@ func (p *Strava) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
user := &AuthUser{
|
||||
Name: extracted.FirstName + " " + extracted.LastName,
|
||||
Username: extracted.Username,
|
||||
AvatarUrl: extracted.ProfileImageUrl,
|
||||
AvatarURL: extracted.ProfileImageURL,
|
||||
RawUser: rawUser,
|
||||
AccessToken: token.AccessToken,
|
||||
RefreshToken: token.RefreshToken,
|
||||
|
||||
+16
-12
@@ -11,6 +11,10 @@ import (
|
||||
"golang.org/x/oauth2/twitch"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Providers[NameTwitch] = wrapFactory(NewTwitchProvider)
|
||||
}
|
||||
|
||||
var _ Provider = (*Twitch)(nil)
|
||||
|
||||
// NameTwitch is the unique name of the Twitch provider.
|
||||
@@ -18,19 +22,19 @@ const NameTwitch string = "twitch"
|
||||
|
||||
// Twitch allows authentication via Twitch OAuth2.
|
||||
type Twitch struct {
|
||||
*baseProvider
|
||||
BaseProvider
|
||||
}
|
||||
|
||||
// NewTwitchProvider creates new Twitch provider instance with some defaults.
|
||||
func NewTwitchProvider() *Twitch {
|
||||
return &Twitch{&baseProvider{
|
||||
return &Twitch{BaseProvider{
|
||||
ctx: context.Background(),
|
||||
displayName: "Twitch",
|
||||
pkce: true,
|
||||
scopes: []string{"user:read:email"},
|
||||
authUrl: twitch.Endpoint.AuthURL,
|
||||
tokenUrl: twitch.Endpoint.TokenURL,
|
||||
userApiUrl: "https://api.twitch.tv/helix/users",
|
||||
authURL: twitch.Endpoint.AuthURL,
|
||||
tokenURL: twitch.Endpoint.TokenURL,
|
||||
userInfoURL: "https://api.twitch.tv/helix/users",
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -38,7 +42,7 @@ func NewTwitchProvider() *Twitch {
|
||||
//
|
||||
// API reference: https://dev.twitch.tv/docs/api/reference#get-users
|
||||
func (p *Twitch) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
data, err := p.FetchRawUserData(token)
|
||||
data, err := p.FetchRawUserInfo(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -54,7 +58,7 @@ func (p *Twitch) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
Login string `json:"login"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Email string `json:"email"`
|
||||
ProfileImageUrl string `json:"profile_image_url"`
|
||||
ProfileImageURL string `json:"profile_image_url"`
|
||||
} `json:"data"`
|
||||
}{}
|
||||
if err := json.Unmarshal(data, &extracted); err != nil {
|
||||
@@ -70,7 +74,7 @@ func (p *Twitch) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
Name: extracted.Data[0].DisplayName,
|
||||
Username: extracted.Data[0].Login,
|
||||
Email: extracted.Data[0].Email,
|
||||
AvatarUrl: extracted.Data[0].ProfileImageUrl,
|
||||
AvatarURL: extracted.Data[0].ProfileImageURL,
|
||||
RawUser: rawUser,
|
||||
AccessToken: token.AccessToken,
|
||||
RefreshToken: token.RefreshToken,
|
||||
@@ -81,16 +85,16 @@ func (p *Twitch) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// FetchRawUserData implements Provider.FetchRawUserData interface.
|
||||
// FetchRawUserInfo implements Provider.FetchRawUserInfo interface.
|
||||
//
|
||||
// This differ from baseProvider because Twitch requires the `Client-Id` header.
|
||||
func (p *Twitch) FetchRawUserData(token *oauth2.Token) ([]byte, error) {
|
||||
req, err := http.NewRequest("GET", p.userApiUrl, nil)
|
||||
func (p *Twitch) FetchRawUserInfo(token *oauth2.Token) ([]byte, error) {
|
||||
req, err := http.NewRequest("GET", p.userInfoURL, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Client-Id", p.clientId)
|
||||
|
||||
return p.sendRawUserDataRequest(req, token)
|
||||
return p.sendRawUserInfoRequest(req, token)
|
||||
}
|
||||
|
||||
+12
-8
@@ -8,6 +8,10 @@ import (
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Providers[NameTwitter] = wrapFactory(NewTwitterProvider)
|
||||
}
|
||||
|
||||
var _ Provider = (*Twitter)(nil)
|
||||
|
||||
// NameTwitter is the unique name of the Twitter provider.
|
||||
@@ -15,12 +19,12 @@ const NameTwitter string = "twitter"
|
||||
|
||||
// Twitter allows authentication via Twitter OAuth2.
|
||||
type Twitter struct {
|
||||
*baseProvider
|
||||
BaseProvider
|
||||
}
|
||||
|
||||
// NewTwitterProvider creates new Twitter provider instance with some defaults.
|
||||
func NewTwitterProvider() *Twitter {
|
||||
return &Twitter{&baseProvider{
|
||||
return &Twitter{BaseProvider{
|
||||
ctx: context.Background(),
|
||||
displayName: "Twitter",
|
||||
pkce: true,
|
||||
@@ -31,9 +35,9 @@ func NewTwitterProvider() *Twitter {
|
||||
// (see https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users-me)
|
||||
"tweet.read",
|
||||
},
|
||||
authUrl: "https://twitter.com/i/oauth2/authorize",
|
||||
tokenUrl: "https://api.twitter.com/2/oauth2/token",
|
||||
userApiUrl: "https://api.twitter.com/2/users/me?user.fields=id,name,username,profile_image_url",
|
||||
authURL: "https://twitter.com/i/oauth2/authorize",
|
||||
tokenURL: "https://api.twitter.com/2/oauth2/token",
|
||||
userInfoURL: "https://api.twitter.com/2/users/me?user.fields=id,name,username,profile_image_url",
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -41,7 +45,7 @@ func NewTwitterProvider() *Twitter {
|
||||
//
|
||||
// API reference: https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users-me
|
||||
func (p *Twitter) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
data, err := p.FetchRawUserData(token)
|
||||
data, err := p.FetchRawUserInfo(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -56,7 +60,7 @@ func (p *Twitter) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Username string `json:"username"`
|
||||
ProfileImageUrl string `json:"profile_image_url"`
|
||||
ProfileImageURL string `json:"profile_image_url"`
|
||||
|
||||
// NB! At the time of writing, Twitter OAuth2 doesn't support returning the user email address
|
||||
// (see https://twittercommunity.com/t/which-api-to-get-user-after-oauth2-authorization/162417/33)
|
||||
@@ -71,7 +75,7 @@ func (p *Twitter) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
Id: extracted.Data.Id,
|
||||
Name: extracted.Data.Name,
|
||||
Username: extracted.Data.Username,
|
||||
AvatarUrl: extracted.Data.ProfileImageUrl,
|
||||
AvatarURL: extracted.Data.ProfileImageURL,
|
||||
RawUser: rawUser,
|
||||
AccessToken: token.AccessToken,
|
||||
RefreshToken: token.RefreshToken,
|
||||
|
||||
+12
-8
@@ -13,6 +13,10 @@ import (
|
||||
"golang.org/x/oauth2/vk"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Providers[NameVK] = wrapFactory(NewVKProvider)
|
||||
}
|
||||
|
||||
var _ Provider = (*VK)(nil)
|
||||
|
||||
// NameVK is the unique name of the VK provider.
|
||||
@@ -20,21 +24,21 @@ const NameVK string = "vk"
|
||||
|
||||
// VK allows authentication via VK OAuth2.
|
||||
type VK struct {
|
||||
*baseProvider
|
||||
BaseProvider
|
||||
}
|
||||
|
||||
// NewVKProvider creates new VK provider instance with some defaults.
|
||||
//
|
||||
// Docs: https://dev.vk.com/api/oauth-parameters
|
||||
func NewVKProvider() *VK {
|
||||
return &VK{&baseProvider{
|
||||
return &VK{BaseProvider{
|
||||
ctx: context.Background(),
|
||||
displayName: "ВКонтакте",
|
||||
pkce: false, // VK currently doesn't support PKCE and throws an error if PKCE params are send
|
||||
scopes: []string{"email"},
|
||||
authUrl: vk.Endpoint.AuthURL,
|
||||
tokenUrl: vk.Endpoint.TokenURL,
|
||||
userApiUrl: "https://api.vk.com/method/users.get?fields=photo_max,screen_name&v=5.131",
|
||||
authURL: vk.Endpoint.AuthURL,
|
||||
tokenURL: vk.Endpoint.TokenURL,
|
||||
userInfoURL: "https://api.vk.com/method/users.get?fields=photo_max,screen_name&v=5.131",
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -42,7 +46,7 @@ func NewVKProvider() *VK {
|
||||
//
|
||||
// API reference: https://dev.vk.com/method/users.get
|
||||
func (p *VK) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
data, err := p.FetchRawUserData(token)
|
||||
data, err := p.FetchRawUserInfo(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -58,7 +62,7 @@ func (p *VK) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
FirstName string `json:"first_name"`
|
||||
LastName string `json:"last_name"`
|
||||
Username string `json:"screen_name"`
|
||||
AvatarUrl string `json:"photo_max"`
|
||||
AvatarURL string `json:"photo_max"`
|
||||
} `json:"response"`
|
||||
}{}
|
||||
|
||||
@@ -74,7 +78,7 @@ func (p *VK) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
Id: strconv.Itoa(extracted.Response[0].Id),
|
||||
Name: strings.TrimSpace(extracted.Response[0].FirstName + " " + extracted.Response[0].LastName),
|
||||
Username: extracted.Response[0].Username,
|
||||
AvatarUrl: extracted.Response[0].AvatarUrl,
|
||||
AvatarURL: extracted.Response[0].AvatarURL,
|
||||
RawUser: rawUser,
|
||||
AccessToken: token.AccessToken,
|
||||
RefreshToken: token.RefreshToken,
|
||||
|
||||
+11
-7
@@ -9,6 +9,10 @@ import (
|
||||
"golang.org/x/oauth2/yandex"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Providers[NameYandex] = wrapFactory(NewYandexProvider)
|
||||
}
|
||||
|
||||
var _ Provider = (*Yandex)(nil)
|
||||
|
||||
// NameYandex is the unique name of the Yandex provider.
|
||||
@@ -16,21 +20,21 @@ const NameYandex string = "yandex"
|
||||
|
||||
// Yandex allows authentication via Yandex OAuth2.
|
||||
type Yandex struct {
|
||||
*baseProvider
|
||||
BaseProvider
|
||||
}
|
||||
|
||||
// NewYandexProvider creates new Yandex provider instance with some defaults.
|
||||
//
|
||||
// Docs: https://yandex.ru/dev/id/doc/en/
|
||||
func NewYandexProvider() *Yandex {
|
||||
return &Yandex{&baseProvider{
|
||||
return &Yandex{BaseProvider{
|
||||
ctx: context.Background(),
|
||||
displayName: "Yandex",
|
||||
pkce: true,
|
||||
scopes: []string{"login:email", "login:avatar", "login:info"},
|
||||
authUrl: yandex.Endpoint.AuthURL,
|
||||
tokenUrl: yandex.Endpoint.TokenURL,
|
||||
userApiUrl: "https://login.yandex.ru/info",
|
||||
authURL: yandex.Endpoint.AuthURL,
|
||||
tokenURL: yandex.Endpoint.TokenURL,
|
||||
userInfoURL: "https://login.yandex.ru/info",
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -38,7 +42,7 @@ func NewYandexProvider() *Yandex {
|
||||
//
|
||||
// API reference: https://yandex.ru/dev/id/doc/en/user-information#response-format
|
||||
func (p *Yandex) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
data, err := p.FetchRawUserData(token)
|
||||
data, err := p.FetchRawUserInfo(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -73,7 +77,7 @@ func (p *Yandex) FetchAuthUser(token *oauth2.Token) (*AuthUser, error) {
|
||||
user.Expiry, _ = types.ParseDateTime(token.Expiry)
|
||||
|
||||
if !extracted.IsAvatarEmpty {
|
||||
user.AvatarUrl = "https://avatars.yandex.net/get-yapic/" + extracted.AvatarId + "/islands-200"
|
||||
user.AvatarURL = "https://avatars.yandex.net/get-yapic/" + extracted.AvatarId + "/islands-200"
|
||||
}
|
||||
|
||||
return user, nil
|
||||
|
||||
Reference in New Issue
Block a user