feat: casdoor support

pull/269/merge
zijiren233 3 months ago
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())
}

@ -3,8 +3,9 @@ package providers
import (
"context"
"encoding/json"
"fmt"
"net/http"
"strings"
"net/url"
"github.com/synctv-org/synctv/internal/provider"
"github.com/synctv-org/synctv/internal/settings"
@ -86,17 +87,20 @@ func (p *logtoProvider) RegistSetting(group string) {
settings.NewStringSetting(
group+"_endpoint", "", group,
settings.WithAfterInitString(func(ss settings.StringSetting, s string) {
s = strings.TrimSuffix(s, "/")
s = strings.TrimSuffix(s, "/oidc")
p.endpoint = s
p.config.Endpoint = oauth2.Endpoint{
AuthURL: s + "/oidc/auth",
TokenURL: s + "/oidc/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) {
s = strings.TrimSuffix(s, "/")
s = strings.TrimSuffix(s, "/oidc")
p.endpoint = s
p.config.Endpoint = oauth2.Endpoint{
AuthURL: s + "/oidc/auth",

Loading…
Cancel
Save