Opt: oauth2 provider

pull/21/head
zijiren233 2 years ago
parent 83843d3c3c
commit d3ced2c376

@ -5,13 +5,20 @@ import (
"os"
"path/filepath"
"github.com/hashicorp/go-hclog"
log "github.com/sirupsen/logrus"
"github.com/synctv-org/synctv/cmd/flags"
"github.com/synctv-org/synctv/internal/conf"
"github.com/synctv-org/synctv/internal/provider"
"github.com/synctv-org/synctv/utils"
)
func InitProvider(ctx context.Context) error {
logOur := log.StandardLogger().Writer()
logLevle := hclog.Info
if flags.Dev {
logLevle = hclog.Debug
}
for _, op := range conf.Conf.OAuth2.Plugins {
utils.OptFilePath(&op.PluginFile)
log.Infof("load oauth2 plugin: %s", op.PluginFile)
@ -20,7 +27,12 @@ func InitProvider(ctx context.Context) error {
log.Errorf("create plugin dir: %s failed: %s", filepath.Dir(op.PluginFile), err)
return err
}
err = provider.InitProviderPlugins(op.PluginFile, op.Arges...)
err = provider.InitProviderPlugins(op.PluginFile, op.Arges, hclog.New(&hclog.LoggerOptions{
Name: op.PluginFile,
Level: logLevle,
Output: logOur,
Color: hclog.ForceColor,
}))
if err != nil {
log.Errorf("load oauth2 plugin: %s failed: %s", op.PluginFile, err)
return err

@ -1,6 +1,9 @@
package conf
import "github.com/synctv-org/synctv/internal/provider"
import (
"github.com/synctv-org/synctv/internal/provider"
"github.com/synctv-org/synctv/internal/provider/providers"
)
type OAuth2Config struct {
Providers map[provider.OAuth2Provider]OAuth2ProviderConfig `yaml:"providers"`
@ -21,7 +24,7 @@ type OAuth2ProviderConfig struct {
func DefaultOAuth2Config() OAuth2Config {
return OAuth2Config{
Providers: map[provider.OAuth2Provider]OAuth2ProviderConfig{
(&provider.GithubProvider{}).Provider(): {
(&providers.GithubProvider{}).Provider(): {
ClientID: "",
ClientSecret: "",
RedirectURL: "",

@ -0,0 +1,68 @@
package provider
import (
"context"
"time"
providerpb "github.com/synctv-org/synctv/proto/provider"
"golang.org/x/oauth2"
)
type GRPCClient struct{ client providerpb.Oauth2PluginClient }
var _ ProviderInterface = (*GRPCClient)(nil)
func (c *GRPCClient) Init(o Oauth2Option) {
c.client.Init(context.Background(), &providerpb.InitReq{
ClientId: o.ClientID,
ClientSecret: o.ClientSecret,
RedirectUrl: o.RedirectURL,
})
}
func (c *GRPCClient) Provider() OAuth2Provider {
resp, err := c.client.Provider(context.Background(), &providerpb.Enpty{})
if err != nil {
return ""
}
return OAuth2Provider(resp.Name)
}
func (c *GRPCClient) NewAuthURL(state string) string {
resp, err := c.client.NewAuthURL(context.Background(), &providerpb.NewAuthURLReq{State: state})
if err != nil {
return ""
}
return resp.Url
}
func (c *GRPCClient) GetToken(ctx context.Context, code string) (*oauth2.Token, error) {
resp, err := c.client.GetToken(ctx, &providerpb.GetTokenReq{Code: code})
if err != nil {
return nil, err
}
return &oauth2.Token{
AccessToken: resp.AccessToken,
TokenType: resp.TokenType,
RefreshToken: resp.RefreshToken,
Expiry: time.Unix(resp.Expiry, 0),
}, nil
}
func (c *GRPCClient) GetUserInfo(ctx context.Context, tk *oauth2.Token) (*UserInfo, error) {
resp, err := c.client.GetUserInfo(ctx, &providerpb.GetUserInfoReq{
Token: &providerpb.Token{
AccessToken: tk.AccessToken,
TokenType: tk.TokenType,
RefreshToken: tk.RefreshToken,
Expiry: tk.Expiry.Unix(),
},
})
if err != nil {
return nil, err
}
return &UserInfo{
Username: resp.Username,
ProviderUserID: uint(resp.ProviderUserId),
}, nil
}

@ -4,148 +4,34 @@ import (
"context"
"fmt"
"os/exec"
"time"
"github.com/hashicorp/go-hclog"
plugin "github.com/hashicorp/go-plugin"
log "github.com/sirupsen/logrus"
"github.com/hashicorp/go-plugin"
sysnotify "github.com/synctv-org/synctv/internal/sysNotify"
providerpb "github.com/synctv-org/synctv/proto/provider"
"golang.org/x/oauth2"
"google.golang.org/grpc"
)
type ProviderPlugin struct {
plugin.Plugin
Impl ProviderInterface
}
func (p *ProviderPlugin) GRPCServer(broker *plugin.GRPCBroker, s *grpc.Server) error {
providerpb.RegisterOauth2PluginServer(s, &GRPCServer{Impl: p.Impl})
func InitProviderPlugins(name string, arg []string, Logger hclog.Logger) error {
client := NewProviderPlugin(name, arg, Logger)
sysnotify.RegisterSysNotifyTask(0, sysnotify.NewSysNotifyTask("plugin", sysnotify.NotifyTypeEXIT, func() error {
client.Kill()
return nil
}
func (p *ProviderPlugin) GRPCClient(ctx context.Context, broker *plugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error) {
return &GRPCClient{client: providerpb.NewOauth2PluginClient(c)}, nil
}
type GRPCServer struct {
providerpb.UnimplementedOauth2PluginServer
Impl ProviderInterface
}
func (s *GRPCServer) Init(ctx context.Context, req *providerpb.InitReq) (*providerpb.Enpty, error) {
s.Impl.Init(Oauth2Option{
ClientID: req.ClientId,
ClientSecret: req.ClientSecret,
RedirectURL: req.RedirectUrl,
})
return &providerpb.Enpty{}, nil
}
func (s *GRPCServer) Provider(ctx context.Context, req *providerpb.Enpty) (*providerpb.ProviderResp, error) {
return &providerpb.ProviderResp{Name: string(s.Impl.Provider())}, nil
}
func (s *GRPCServer) NewAuthURL(ctx context.Context, req *providerpb.NewAuthURLReq) (*providerpb.NewAuthURLResp, error) {
return &providerpb.NewAuthURLResp{Url: s.Impl.NewAuthURL(req.State)}, nil
}
func (s *GRPCServer) GetToken(ctx context.Context, req *providerpb.GetTokenReq) (*providerpb.Token, error) {
token, err := s.Impl.GetToken(ctx, req.Code)
if err != nil {
return nil, err
}
return &providerpb.Token{
AccessToken: token.AccessToken,
TokenType: token.TokenType,
RefreshToken: token.RefreshToken,
Expiry: token.Expiry.Unix(),
}, nil
}
func (s *GRPCServer) GetUserInfo(ctx context.Context, req *providerpb.GetUserInfoReq) (*providerpb.GetUserInfoResp, error) {
userInfo, err := s.Impl.GetUserInfo(ctx, &oauth2.Token{
AccessToken: req.Token.AccessToken,
TokenType: req.Token.TokenType,
Expiry: time.Unix(req.Token.Expiry, 0),
RefreshToken: req.Token.RefreshToken,
})
if err != nil {
return nil, err
}
resp := &providerpb.GetUserInfoResp{
Username: userInfo.Username,
ProviderUserId: uint64(userInfo.ProviderUserID),
}
if userInfo.TokenRefreshed != nil {
resp.TokenRefreshed = &providerpb.Token{
AccessToken: userInfo.TokenRefreshed.Token.AccessToken,
TokenType: userInfo.TokenRefreshed.Token.TokenType,
RefreshToken: userInfo.TokenRefreshed.Token.RefreshToken,
Expiry: userInfo.TokenRefreshed.Token.Expiry.Unix(),
}
}
return resp, nil
}
type GRPCClient struct{ client providerpb.Oauth2PluginClient }
var _ ProviderInterface = (*GRPCClient)(nil)
func (c *GRPCClient) Init(o Oauth2Option) {
c.client.Init(context.Background(), &providerpb.InitReq{
ClientId: o.ClientID,
ClientSecret: o.ClientSecret,
RedirectUrl: o.RedirectURL,
})
}
func (c *GRPCClient) Provider() OAuth2Provider {
resp, err := c.client.Provider(context.Background(), &providerpb.Enpty{})
if err != nil {
return ""
}
return OAuth2Provider(resp.Name)
}
func (c *GRPCClient) NewAuthURL(state string) string {
resp, err := c.client.NewAuthURL(context.Background(), &providerpb.NewAuthURLReq{State: state})
}))
c, err := client.Client()
if err != nil {
return ""
return err
}
return resp.Url
}
func (c *GRPCClient) GetToken(ctx context.Context, code string) (*oauth2.Token, error) {
resp, err := c.client.GetToken(ctx, &providerpb.GetTokenReq{Code: code})
i, err := c.Dispense("Provider")
if err != nil {
return nil, err
return err
}
return &oauth2.Token{
AccessToken: resp.AccessToken,
TokenType: resp.TokenType,
RefreshToken: resp.RefreshToken,
Expiry: time.Unix(resp.Expiry, 0),
}, nil
}
func (c *GRPCClient) GetUserInfo(ctx context.Context, tk *oauth2.Token) (*UserInfo, error) {
resp, err := c.client.GetUserInfo(ctx, &providerpb.GetUserInfoReq{
Token: &providerpb.Token{
AccessToken: tk.AccessToken,
TokenType: tk.TokenType,
RefreshToken: tk.RefreshToken,
Expiry: tk.Expiry.Unix(),
},
})
if err != nil {
return nil, err
provider, ok := i.(ProviderInterface)
if !ok {
return fmt.Errorf("%s not implement ProviderInterface", name)
}
return &UserInfo{
Username: resp.Username,
ProviderUserID: uint(resp.ProviderUserId),
}, nil
RegisterProvider(provider)
return nil
}
var HandshakeConfig = plugin.HandshakeConfig{
@ -158,35 +44,27 @@ var pluginMap = map[string]plugin.Plugin{
"Provider": &ProviderPlugin{},
}
func InitProviderPlugins(name string, arg ...string) error {
client := plugin.NewClient(&plugin.ClientConfig{
type ProviderPlugin struct {
plugin.Plugin
Impl ProviderInterface
}
func (p *ProviderPlugin) GRPCServer(broker *plugin.GRPCBroker, s *grpc.Server) error {
providerpb.RegisterOauth2PluginServer(s, &GRPCServer{Impl: p.Impl})
return nil
}
func (p *ProviderPlugin) GRPCClient(ctx context.Context, broker *plugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error) {
return &GRPCClient{client: providerpb.NewOauth2PluginClient(c)}, nil
}
func NewProviderPlugin(name string, arg []string, Logger hclog.Logger) *plugin.Client {
return plugin.NewClient(&plugin.ClientConfig{
HandshakeConfig: HandshakeConfig,
Plugins: pluginMap,
Cmd: exec.Command(name, arg...),
AllowedProtocols: []plugin.Protocol{
plugin.ProtocolGRPC},
Logger: hclog.New(&hclog.LoggerOptions{
Name: "plugin",
Output: log.StandardLogger().Writer(),
Level: hclog.Debug,
}),
Logger: Logger,
})
sysnotify.RegisterSysNotifyTask(0, sysnotify.NewSysNotifyTask("plugin", sysnotify.NotifyTypeEXIT, func() error {
client.Kill()
return nil
}))
c, err := client.Client()
if err != nil {
return err
}
i, err := c.Dispense("Provider")
if err != nil {
return err
}
provider, ok := i.(ProviderInterface)
if !ok {
return fmt.Errorf("%s not implement ProviderInterface", name)
}
registerProvider(provider)
return nil
}

@ -10,6 +10,21 @@ import (
"golang.org/x/oauth2"
)
// go build -o gitee ./internal/provider/plugins/gitee.go
//
// mv gitee {data-dir}/plugins/oauth2/gitee
//
// config.yaml:
//
// oauth2:
// providers:
// gitee:
// client_id: xxx
// client_secret: xxx
// redirect_url: xxx
// plugins:
// - plugin_file: plugins/oauth2/gitee
// arges: []
type GiteeProvider struct {
config oauth2.Config
}

@ -9,11 +9,6 @@ import (
type OAuth2Provider string
var (
enabledProviders map[OAuth2Provider]ProviderInterface
allowedProviders = make(map[OAuth2Provider]ProviderInterface)
)
type TokenRefreshed struct {
Refreshed bool
Token *oauth2.Token
@ -39,6 +34,11 @@ type ProviderInterface interface {
GetUserInfo(context.Context, *oauth2.Token) (*UserInfo, error)
}
var (
enabledProviders map[OAuth2Provider]ProviderInterface
allowedProviders = make(map[OAuth2Provider]ProviderInterface)
)
func InitProvider(p OAuth2Provider, c Oauth2Option) error {
pi, ok := allowedProviders[p]
if !ok {
@ -52,7 +52,7 @@ func InitProvider(p OAuth2Provider, c Oauth2Option) error {
return nil
}
func registerProvider(ps ...ProviderInterface) {
func RegisterProvider(ps ...ProviderInterface) {
for _, p := range ps {
allowedProviders[p.Provider()] = p
}

@ -1,4 +1,4 @@
package provider
package providers
import (
"context"
@ -6,6 +6,7 @@ import (
"net/http"
json "github.com/json-iterator/go"
"github.com/synctv-org/synctv/internal/provider"
"golang.org/x/oauth2"
)
@ -14,7 +15,7 @@ type BaiduNetDiskProvider struct {
config oauth2.Config
}
func (p *BaiduNetDiskProvider) Init(c Oauth2Option) {
func (p *BaiduNetDiskProvider) Init(c provider.Oauth2Option) {
p.config.Scopes = []string{"basic", "netdisk"}
p.config.Endpoint = oauth2.Endpoint{
AuthURL: "https://openapi.baidu.com/oauth/2.0/authorize",
@ -25,7 +26,7 @@ func (p *BaiduNetDiskProvider) Init(c Oauth2Option) {
p.config.RedirectURL = c.RedirectURL
}
func (p *BaiduNetDiskProvider) Provider() OAuth2Provider {
func (p *BaiduNetDiskProvider) Provider() provider.OAuth2Provider {
return "baidu-netdisk"
}
@ -36,7 +37,7 @@ func (p *BaiduNetDiskProvider) NewAuthURL(state string) string {
func (p *BaiduNetDiskProvider) GetToken(ctx context.Context, code string) (*oauth2.Token, error) {
return p.config.Exchange(ctx, code)
}
func (p *BaiduNetDiskProvider) GetUserInfo(ctx context.Context, tk *oauth2.Token) (*UserInfo, error) {
func (p *BaiduNetDiskProvider) GetUserInfo(ctx context.Context, tk *oauth2.Token) (*provider.UserInfo, error) {
client := p.config.Client(ctx, tk)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("https://pan.baidu.com/rest/2.0/xpan/nas?method=uinfo&access_token=%s", tk.AccessToken), nil)
if err != nil {
@ -55,14 +56,14 @@ func (p *BaiduNetDiskProvider) GetUserInfo(ctx context.Context, tk *oauth2.Token
if ui.Errno != 0 {
return nil, fmt.Errorf("baidu oauth2 get user info error: %s", ui.Errmsg)
}
return &UserInfo{
return &provider.UserInfo{
Username: ui.BaiduName,
ProviderUserID: ui.Uk,
}, nil
}
func init() {
registerProvider(new(BaiduNetDiskProvider))
provider.RegisterProvider(new(BaiduNetDiskProvider))
}
type baiduNetDiskProviderUserInfo struct {

@ -1,4 +1,4 @@
package provider
package providers
import (
"context"
@ -7,6 +7,7 @@ import (
"net/http"
json "github.com/json-iterator/go"
"github.com/synctv-org/synctv/internal/provider"
"github.com/zijiren233/stream"
"golang.org/x/oauth2"
)
@ -16,7 +17,7 @@ type BaiduProvider struct {
config oauth2.Config
}
func (p *BaiduProvider) Init(c Oauth2Option) {
func (p *BaiduProvider) Init(c provider.Oauth2Option) {
p.config.Scopes = []string{"basic"}
p.config.Endpoint = oauth2.Endpoint{
AuthURL: "https://openapi.baidu.com/oauth/2.0/authorize",
@ -27,7 +28,7 @@ func (p *BaiduProvider) Init(c Oauth2Option) {
p.config.RedirectURL = c.RedirectURL
}
func (p *BaiduProvider) Provider() OAuth2Provider {
func (p *BaiduProvider) Provider() provider.OAuth2Provider {
return "baidu"
}
@ -39,7 +40,7 @@ func (p *BaiduProvider) GetToken(ctx context.Context, code string) (*oauth2.Toke
return p.config.Exchange(ctx, code)
}
func (p *BaiduProvider) GetUserInfo(ctx context.Context, tk *oauth2.Token) (*UserInfo, error) {
func (p *BaiduProvider) GetUserInfo(ctx context.Context, tk *oauth2.Token) (*provider.UserInfo, error) {
client := p.config.Client(ctx, tk)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("https://openapi.baidu.com/rest/2.0/passport/users/getLoggedInUser?access_token=%s", tk.AccessToken), nil)
if err != nil {
@ -55,14 +56,14 @@ func (p *BaiduProvider) GetUserInfo(ctx context.Context, tk *oauth2.Token) (*Use
if err != nil {
return nil, err
}
return &UserInfo{
return &provider.UserInfo{
Username: ui.Uname,
ProviderUserID: uint(crc32.ChecksumIEEE(stream.StringToBytes(ui.Openid))),
}, nil
}
func init() {
registerProvider(new(BaiduProvider))
provider.RegisterProvider(new(BaiduProvider))
}
type baiduProviderUserInfo struct {

@ -1,10 +1,11 @@
package provider
package providers
import (
"context"
"net/http"
json "github.com/json-iterator/go"
"github.com/synctv-org/synctv/internal/provider"
"golang.org/x/oauth2"
)
@ -12,7 +13,7 @@ type GiteeProvider struct {
config oauth2.Config
}
func (p *GiteeProvider) Init(c Oauth2Option) {
func (p *GiteeProvider) Init(c provider.Oauth2Option) {
p.config.Scopes = []string{"user_info"}
p.config.Endpoint = oauth2.Endpoint{
AuthURL: "https://gitee.com/oauth/authorize",
@ -23,7 +24,7 @@ func (p *GiteeProvider) Init(c Oauth2Option) {
p.config.RedirectURL = c.RedirectURL
}
func (p *GiteeProvider) Provider() OAuth2Provider {
func (p *GiteeProvider) Provider() provider.OAuth2Provider {
return "gitee"
}
@ -35,7 +36,7 @@ func (p *GiteeProvider) GetToken(ctx context.Context, code string) (*oauth2.Toke
return p.config.Exchange(ctx, code)
}
func (p *GiteeProvider) GetUserInfo(ctx context.Context, tk *oauth2.Token) (*UserInfo, error) {
func (p *GiteeProvider) GetUserInfo(ctx context.Context, tk *oauth2.Token) (*provider.UserInfo, error) {
client := p.config.Client(ctx, tk)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://gitee.com/api/v5/user", nil)
if err != nil {
@ -51,7 +52,7 @@ func (p *GiteeProvider) GetUserInfo(ctx context.Context, tk *oauth2.Token) (*Use
if err != nil {
return nil, err
}
return &UserInfo{
return &provider.UserInfo{
Username: ui.Login,
ProviderUserID: ui.ID,
}, nil
@ -63,5 +64,5 @@ type giteeUserInfo struct {
}
func init() {
registerProvider(new(GiteeProvider))
provider.RegisterProvider(new(GiteeProvider))
}

@ -1,10 +1,11 @@
package provider
package providers
import (
"context"
"net/http"
json "github.com/json-iterator/go"
"github.com/synctv-org/synctv/internal/provider"
"golang.org/x/oauth2"
"golang.org/x/oauth2/github"
)
@ -13,7 +14,7 @@ type GithubProvider struct {
config oauth2.Config
}
func (p *GithubProvider) Init(c Oauth2Option) {
func (p *GithubProvider) Init(c provider.Oauth2Option) {
p.config.Scopes = []string{"user"}
p.config.Endpoint = github.Endpoint
p.config.ClientID = c.ClientID
@ -21,7 +22,7 @@ func (p *GithubProvider) Init(c Oauth2Option) {
p.config.RedirectURL = c.RedirectURL
}
func (p *GithubProvider) Provider() OAuth2Provider {
func (p *GithubProvider) Provider() provider.OAuth2Provider {
return "github"
}
@ -33,7 +34,7 @@ func (p *GithubProvider) GetToken(ctx context.Context, code string) (*oauth2.Tok
return p.config.Exchange(ctx, code)
}
func (p *GithubProvider) GetUserInfo(ctx context.Context, tk *oauth2.Token) (*UserInfo, error) {
func (p *GithubProvider) GetUserInfo(ctx context.Context, tk *oauth2.Token) (*provider.UserInfo, error) {
client := p.config.Client(ctx, tk)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://api.github.com/user", nil)
if err != nil {
@ -49,7 +50,7 @@ func (p *GithubProvider) GetUserInfo(ctx context.Context, tk *oauth2.Token) (*Us
if err != nil {
return nil, err
}
return &UserInfo{
return &provider.UserInfo{
Username: ui.Login,
ProviderUserID: ui.ID,
}, nil
@ -61,5 +62,5 @@ type githubUserInfo struct {
}
func init() {
registerProvider(new(GithubProvider))
provider.RegisterProvider(new(GithubProvider))
}

@ -1,9 +1,10 @@
package provider
package providers
import (
"context"
"net/http"
"github.com/synctv-org/synctv/internal/provider"
"golang.org/x/oauth2"
"golang.org/x/oauth2/gitlab"
)
@ -12,7 +13,7 @@ type GitlabProvider struct {
config oauth2.Config
}
func (g *GitlabProvider) Init(c Oauth2Option) {
func (g *GitlabProvider) Init(c provider.Oauth2Option) {
g.config.Scopes = []string{"read_user"}
g.config.Endpoint = gitlab.Endpoint
g.config.ClientID = c.ClientID
@ -20,7 +21,7 @@ func (g *GitlabProvider) Init(c Oauth2Option) {
g.config.RedirectURL = c.RedirectURL
}
func (g *GitlabProvider) Provider() OAuth2Provider {
func (g *GitlabProvider) Provider() provider.OAuth2Provider {
return "gitlab"
}
@ -32,7 +33,7 @@ func (g *GitlabProvider) GetToken(ctx context.Context, code string) (*oauth2.Tok
return g.config.Exchange(ctx, code)
}
func (g *GitlabProvider) GetUserInfo(ctx context.Context, tk *oauth2.Token) (*UserInfo, error) {
func (g *GitlabProvider) GetUserInfo(ctx context.Context, tk *oauth2.Token) (*provider.UserInfo, error) {
client := g.config.Client(ctx, tk)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://gitlab.com/api/v4/user", nil)
if err != nil {
@ -43,9 +44,9 @@ func (g *GitlabProvider) GetUserInfo(ctx context.Context, tk *oauth2.Token) (*Us
return nil, err
}
defer resp.Body.Close()
return nil, FormatErrNotImplemented("gitlab")
return nil, provider.FormatErrNotImplemented("gitlab")
}
func init() {
registerProvider(new(GitlabProvider))
provider.RegisterProvider(new(GitlabProvider))
}

@ -1,10 +1,11 @@
package provider
package providers
import (
"context"
"net/http"
json "github.com/json-iterator/go"
"github.com/synctv-org/synctv/internal/provider"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
)
@ -13,7 +14,7 @@ type GoogleProvider struct {
config oauth2.Config
}
func (g *GoogleProvider) Init(c Oauth2Option) {
func (g *GoogleProvider) Init(c provider.Oauth2Option) {
g.config.Scopes = []string{"profile"}
g.config.Endpoint = google.Endpoint
g.config.ClientID = c.ClientID
@ -21,7 +22,7 @@ func (g *GoogleProvider) Init(c Oauth2Option) {
g.config.RedirectURL = c.RedirectURL
}
func (g *GoogleProvider) Provider() OAuth2Provider {
func (g *GoogleProvider) Provider() provider.OAuth2Provider {
return "google"
}
@ -33,7 +34,7 @@ func (g *GoogleProvider) GetToken(ctx context.Context, code string) (*oauth2.Tok
return g.config.Exchange(ctx, code)
}
func (g *GoogleProvider) GetUserInfo(ctx context.Context, tk *oauth2.Token) (*UserInfo, error) {
func (g *GoogleProvider) GetUserInfo(ctx context.Context, tk *oauth2.Token) (*provider.UserInfo, error) {
client := g.config.Client(ctx, tk)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://www.googleapis.com/oauth2/v2/userinfo", nil)
if err != nil {
@ -49,14 +50,14 @@ func (g *GoogleProvider) GetUserInfo(ctx context.Context, tk *oauth2.Token) (*Us
if err != nil {
return nil, err
}
return &UserInfo{
return &provider.UserInfo{
Username: ui.Name,
ProviderUserID: ui.ID,
}, nil
}
func init() {
registerProvider(new(GoogleProvider))
provider.RegisterProvider(new(GoogleProvider))
}
type googleUserInfo struct {

@ -1,4 +1,4 @@
package provider
package providers
import (
"context"
@ -6,6 +6,7 @@ import (
"net/http"
json "github.com/json-iterator/go"
"github.com/synctv-org/synctv/internal/provider"
"github.com/zijiren233/stream"
"golang.org/x/oauth2"
"golang.org/x/oauth2/microsoft"
@ -15,7 +16,7 @@ type MicrosoftProvider struct {
config oauth2.Config
}
func (p *MicrosoftProvider) Init(c Oauth2Option) {
func (p *MicrosoftProvider) Init(c provider.Oauth2Option) {
p.config.Scopes = []string{"user.read"}
p.config.Endpoint = microsoft.LiveConnectEndpoint
p.config.ClientID = c.ClientID
@ -23,7 +24,7 @@ func (p *MicrosoftProvider) Init(c Oauth2Option) {
p.config.RedirectURL = c.RedirectURL
}
func (p *MicrosoftProvider) Provider() OAuth2Provider {
func (p *MicrosoftProvider) Provider() provider.OAuth2Provider {
return "microsoft"
}
@ -35,7 +36,7 @@ func (p *MicrosoftProvider) GetToken(ctx context.Context, code string) (*oauth2.
return p.config.Exchange(ctx, code)
}
func (p *MicrosoftProvider) GetUserInfo(ctx context.Context, tk *oauth2.Token) (*UserInfo, error) {
func (p *MicrosoftProvider) GetUserInfo(ctx context.Context, tk *oauth2.Token) (*provider.UserInfo, error) {
client := p.config.Client(ctx, tk)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://graph.microsoft.com/v1.0/me", nil)
if err != nil {
@ -51,7 +52,7 @@ func (p *MicrosoftProvider) GetUserInfo(ctx context.Context, tk *oauth2.Token) (
if err != nil {
return nil, err
}
return &UserInfo{
return &provider.UserInfo{
Username: ui.DisplayName,
ProviderUserID: uint(crc32.ChecksumIEEE(stream.StringToBytes(ui.ID))),
}, nil
@ -63,5 +64,5 @@ type microsoftUserInfo struct {
}
func init() {
registerProvider(new(MicrosoftProvider))
provider.RegisterProvider(new(MicrosoftProvider))
}

@ -0,0 +1,69 @@
package provider
import (
"context"
"time"
providerpb "github.com/synctv-org/synctv/proto/provider"
"golang.org/x/oauth2"
)
type GRPCServer struct {
providerpb.UnimplementedOauth2PluginServer
Impl ProviderInterface
}
func (s *GRPCServer) Init(ctx context.Context, req *providerpb.InitReq) (*providerpb.Enpty, error) {
s.Impl.Init(Oauth2Option{
ClientID: req.ClientId,
ClientSecret: req.ClientSecret,
RedirectURL: req.RedirectUrl,
})
return &providerpb.Enpty{}, nil
}
func (s *GRPCServer) Provider(ctx context.Context, req *providerpb.Enpty) (*providerpb.ProviderResp, error) {
return &providerpb.ProviderResp{Name: string(s.Impl.Provider())}, nil
}
func (s *GRPCServer) NewAuthURL(ctx context.Context, req *providerpb.NewAuthURLReq) (*providerpb.NewAuthURLResp, error) {
return &providerpb.NewAuthURLResp{Url: s.Impl.NewAuthURL(req.State)}, nil
}
func (s *GRPCServer) GetToken(ctx context.Context, req *providerpb.GetTokenReq) (*providerpb.Token, error) {
token, err := s.Impl.GetToken(ctx, req.Code)
if err != nil {
return nil, err
}
return &providerpb.Token{
AccessToken: token.AccessToken,
TokenType: token.TokenType,
RefreshToken: token.RefreshToken,
Expiry: token.Expiry.Unix(),
}, nil
}
func (s *GRPCServer) GetUserInfo(ctx context.Context, req *providerpb.GetUserInfoReq) (*providerpb.GetUserInfoResp, error) {
userInfo, err := s.Impl.GetUserInfo(ctx, &oauth2.Token{
AccessToken: req.Token.AccessToken,
TokenType: req.Token.TokenType,
Expiry: time.Unix(req.Token.Expiry, 0),
RefreshToken: req.Token.RefreshToken,
})
if err != nil {
return nil, err
}
resp := &providerpb.GetUserInfoResp{
Username: userInfo.Username,
ProviderUserId: uint64(userInfo.ProviderUserID),
}
if userInfo.TokenRefreshed != nil {
resp.TokenRefreshed = &providerpb.Token{
AccessToken: userInfo.TokenRefreshed.Token.AccessToken,
TokenType: userInfo.TokenRefreshed.Token.TokenType,
RefreshToken: userInfo.TokenRefreshed.Token.RefreshToken,
Expiry: userInfo.TokenRefreshed.Token.Expiry.Unix(),
}
}
return resp, nil
}
Loading…
Cancel
Save