mirror of https://github.com/synctv-org/synctv
feat: casdoor support
parent
61dba4865e
commit
18fd47f213
@ -0,0 +1,118 @@
|
||||
package providers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/synctv-org/synctv/internal/provider"
|
||||
"github.com/synctv-org/synctv/internal/settings"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
// https://door.casdoor.com/.well-known/openid-configuration
|
||||
type casdoorProvider struct {
|
||||
config oauth2.Config
|
||||
endpoint string
|
||||
}
|
||||
|
||||
func newCasdoorProvider() provider.Interface {
|
||||
return &casdoorProvider{
|
||||
config: oauth2.Config{
|
||||
Scopes: []string{"profile", "email", "phone", "name", "openid"},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (p *casdoorProvider) Init(opt provider.Oauth2Option) {
|
||||
p.config.ClientID = opt.ClientID
|
||||
p.config.ClientSecret = opt.ClientSecret
|
||||
p.config.RedirectURL = opt.RedirectURL
|
||||
}
|
||||
|
||||
func (p *casdoorProvider) NewAuthURL(ctx context.Context, state string) (string, error) {
|
||||
return p.config.AuthCodeURL(state, oauth2.AccessTypeOnline), nil
|
||||
}
|
||||
|
||||
func (p *casdoorProvider) GetToken(ctx context.Context, code string) (*oauth2.Token, error) {
|
||||
return p.config.Exchange(ctx, code)
|
||||
}
|
||||
|
||||
func (p *casdoorProvider) RefreshToken(ctx context.Context, token string) (*oauth2.Token, error) {
|
||||
return p.config.TokenSource(ctx, &oauth2.Token{RefreshToken: token}).Token()
|
||||
}
|
||||
|
||||
func (p *casdoorProvider) GetUserInfo(ctx context.Context, code string) (*provider.UserInfo, error) {
|
||||
tk, err := p.GetToken(ctx, code)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client := p.config.Client(ctx, tk)
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, p.endpoint+"/api/userinfo", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
var ui casdoorUserInfo
|
||||
err = json.NewDecoder(resp.Body).Decode(&ui)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
un := ui.PreferredUsername
|
||||
if un == "" {
|
||||
un = ui.Name
|
||||
}
|
||||
return &provider.UserInfo{
|
||||
ProviderUserID: ui.Sub,
|
||||
Username: un,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type casdoorUserInfo struct {
|
||||
Sub string `json:"sub"`
|
||||
PreferredUsername string `json:"preferred_username"`
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
Phone string `json:"phone"`
|
||||
}
|
||||
|
||||
func (p *casdoorProvider) RegistSetting(group string) {
|
||||
settings.NewStringSetting(
|
||||
group+"_endpoint", "", group,
|
||||
settings.WithAfterInitString(func(ss settings.StringSetting, s string) {
|
||||
p.endpoint = s
|
||||
p.config.Endpoint = oauth2.Endpoint{
|
||||
AuthURL: s + "/login/oauth/authorize",
|
||||
TokenURL: s + "/api/login/oauth/access_token",
|
||||
}
|
||||
}),
|
||||
settings.WithBeforeSetString(func(ss settings.StringSetting, s string) (string, error) {
|
||||
u, err := url.Parse(s)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fmt.Sprintf("%s://%s", u.Scheme, u.Host), nil
|
||||
}),
|
||||
settings.WithAfterSetString(func(ss settings.StringSetting, s string) {
|
||||
p.endpoint = s
|
||||
p.config.Endpoint = oauth2.Endpoint{
|
||||
AuthURL: s + "/login/oauth/authorize",
|
||||
TokenURL: s + "/api/login/oauth/access_token",
|
||||
}
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
func (p *casdoorProvider) Provider() provider.OAuth2Provider {
|
||||
return "casdoor"
|
||||
}
|
||||
|
||||
func init() {
|
||||
RegisterProvider(newCasdoorProvider())
|
||||
}
|
Loading…
Reference in New Issue