234 lines
7.5 KiB
Go
234 lines
7.5 KiB
Go
package auth
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"sync"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
// OAuthConfigYAML OAuth配置结构 (从YAML文件加载)
|
|
type OAuthConfigYAML struct {
|
|
Common CommonConfig `yaml:"common"`
|
|
WeChat WeChatOAuthConfig `yaml:"wechat"`
|
|
Google GoogleOAuthConfig `yaml:"google"`
|
|
Facebook FacebookOAuthConfig `yaml:"facebook"`
|
|
QQ QQOAuthConfig `yaml:"qq"`
|
|
Weibo WeiboOAuthConfig `yaml:"weibo"`
|
|
Twitter TwitterOAuthConfig `yaml:"twitter"`
|
|
}
|
|
|
|
// CommonConfig 通用配置
|
|
type CommonConfig struct {
|
|
RedirectBaseURL string `yaml:"redirect_base_url"`
|
|
CallbackPath string `yaml:"callback_path"`
|
|
}
|
|
|
|
// WeChatOAuthConfig 微信OAuth配置
|
|
type WeChatOAuthConfig struct {
|
|
Enabled bool `yaml:"enabled"`
|
|
AppID string `yaml:"app_id"`
|
|
AppSecret string `yaml:"app_secret"`
|
|
Scopes []string `yaml:"scopes"`
|
|
AuthURL string `yaml:"auth_url"`
|
|
TokenURL string `yaml:"token_url"`
|
|
UserInfoURL string `yaml:"user_info_url"`
|
|
MiniProgram MiniProgramConfig `yaml:"mini_program"`
|
|
}
|
|
|
|
// MiniProgramConfig 小程序配置
|
|
type MiniProgramConfig struct {
|
|
Enabled bool `yaml:"enabled"`
|
|
AppID string `yaml:"app_id"`
|
|
AppSecret string `yaml:"app_secret"`
|
|
}
|
|
|
|
// GoogleOAuthConfig Google OAuth配置
|
|
type GoogleOAuthConfig struct {
|
|
Enabled bool `yaml:"enabled"`
|
|
ClientID string `yaml:"client_id"`
|
|
ClientSecret string `yaml:"client_secret"`
|
|
Scopes []string `yaml:"scopes"`
|
|
AuthURL string `yaml:"auth_url"`
|
|
TokenURL string `yaml:"token_url"`
|
|
UserInfoURL string `yaml:"user_info_url"`
|
|
JWTAuthURL string `yaml:"jwt_auth_url"`
|
|
}
|
|
|
|
// FacebookOAuthConfig Facebook OAuth配置
|
|
type FacebookOAuthConfig struct {
|
|
Enabled bool `yaml:"enabled"`
|
|
AppID string `yaml:"app_id"`
|
|
AppSecret string `yaml:"app_secret"`
|
|
Scopes []string `yaml:"scopes"`
|
|
AuthURL string `yaml:"auth_url"`
|
|
TokenURL string `yaml:"token_url"`
|
|
UserInfoURL string `yaml:"user_info_url"`
|
|
}
|
|
|
|
// QQOAuthConfig QQ OAuth配置
|
|
type QQOAuthConfig struct {
|
|
Enabled bool `yaml:"enabled"`
|
|
AppID string `yaml:"app_id"`
|
|
AppKey string `yaml:"app_key"`
|
|
AppSecret string `yaml:"app_secret"`
|
|
RedirectURI string `yaml:"redirect_uri"`
|
|
Scopes []string `yaml:"scopes"`
|
|
AuthURL string `yaml:"auth_url"`
|
|
TokenURL string `yaml:"token_url"`
|
|
OpenIDURL string `yaml:"openid_url"`
|
|
UserInfoURL string `yaml:"user_info_url"`
|
|
}
|
|
|
|
// WeiboOAuthConfig 微博OAuth配置
|
|
type WeiboOAuthConfig struct {
|
|
Enabled bool `yaml:"enabled"`
|
|
AppKey string `yaml:"app_key"`
|
|
AppSecret string `yaml:"app_secret"`
|
|
RedirectURI string `yaml:"redirect_uri"`
|
|
Scopes []string `yaml:"scopes"`
|
|
AuthURL string `yaml:"auth_url"`
|
|
TokenURL string `yaml:"token_url"`
|
|
UserInfoURL string `yaml:"user_info_url"`
|
|
}
|
|
|
|
// TwitterOAuthConfig Twitter OAuth配置
|
|
type TwitterOAuthConfig struct {
|
|
Enabled bool `yaml:"enabled"`
|
|
ClientID string `yaml:"client_id"`
|
|
ClientSecret string `yaml:"client_secret"`
|
|
Scopes []string `yaml:"scopes"`
|
|
AuthURL string `yaml:"auth_url"`
|
|
TokenURL string `yaml:"token_url"`
|
|
UserInfoURL string `yaml:"user_info_url"`
|
|
}
|
|
|
|
var (
|
|
oauthConfig *OAuthConfigYAML
|
|
oauthConfigOnce sync.Once
|
|
)
|
|
|
|
// LoadOAuthConfig 加载OAuth配置
|
|
func LoadOAuthConfig(configPath string) (*OAuthConfigYAML, error) {
|
|
var err error
|
|
oauthConfigOnce.Do(func() {
|
|
// 如果未指定配置文件,尝试默认路径
|
|
if configPath == "" {
|
|
configPath = filepath.Join("configs", "oauth_config.yaml")
|
|
}
|
|
|
|
// 如果配置文件不存在,尝试从环境变量加载
|
|
if _, statErr := os.Stat(configPath); os.IsNotExist(statErr) {
|
|
oauthConfig = loadFromEnv()
|
|
return
|
|
}
|
|
|
|
// 从文件加载配置
|
|
data, readErr := os.ReadFile(configPath)
|
|
if readErr != nil {
|
|
oauthConfig = loadFromEnv()
|
|
err = fmt.Errorf("failed to read oauth config file: %w", readErr)
|
|
return
|
|
}
|
|
|
|
oauthConfig = &OAuthConfigYAML{}
|
|
if unmarshalErr := yaml.Unmarshal(data, oauthConfig); unmarshalErr != nil {
|
|
oauthConfig = loadFromEnv()
|
|
err = fmt.Errorf("failed to parse oauth config file: %w", unmarshalErr)
|
|
return
|
|
}
|
|
})
|
|
|
|
return oauthConfig, err
|
|
}
|
|
|
|
// loadFromEnv 从环境变量加载配置
|
|
func loadFromEnv() *OAuthConfigYAML {
|
|
return &OAuthConfigYAML{
|
|
Common: CommonConfig{
|
|
RedirectBaseURL: getEnv("OAUTH_REDIRECT_BASE_URL", "http://localhost:8080"),
|
|
CallbackPath: getEnv("OAUTH_CALLBACK_PATH", "/api/v1/auth/oauth/callback"),
|
|
},
|
|
WeChat: WeChatOAuthConfig{
|
|
Enabled: getEnvBool("WECHAT_OAUTH_ENABLED", false),
|
|
AppID: getEnv("WECHAT_APP_ID", ""),
|
|
AppSecret: getEnv("WECHAT_APP_SECRET", ""),
|
|
AuthURL: "https://open.weixin.qq.com/connect/qrconnect",
|
|
TokenURL: "https://api.weixin.qq.com/sns/oauth2/access_token",
|
|
UserInfoURL: "https://api.weixin.qq.com/sns/userinfo",
|
|
},
|
|
Google: GoogleOAuthConfig{
|
|
Enabled: getEnvBool("GOOGLE_OAUTH_ENABLED", false),
|
|
ClientID: getEnv("GOOGLE_CLIENT_ID", ""),
|
|
ClientSecret: getEnv("GOOGLE_CLIENT_SECRET", ""),
|
|
AuthURL: "https://accounts.google.com/o/oauth2/v2/auth",
|
|
TokenURL: "https://oauth2.googleapis.com/token",
|
|
UserInfoURL: "https://www.googleapis.com/oauth2/v2/userinfo",
|
|
JWTAuthURL: "https://oauth2.googleapis.com/tokeninfo",
|
|
},
|
|
Facebook: FacebookOAuthConfig{
|
|
Enabled: getEnvBool("FACEBOOK_OAUTH_ENABLED", false),
|
|
AppID: getEnv("FACEBOOK_APP_ID", ""),
|
|
AppSecret: getEnv("FACEBOOK_APP_SECRET", ""),
|
|
AuthURL: "https://www.facebook.com/v18.0/dialog/oauth",
|
|
TokenURL: "https://graph.facebook.com/v18.0/oauth/access_token",
|
|
UserInfoURL: "https://graph.facebook.com/v18.0/me?fields=id,name,email,picture",
|
|
},
|
|
QQ: QQOAuthConfig{
|
|
Enabled: getEnvBool("QQ_OAUTH_ENABLED", false),
|
|
AppID: getEnv("QQ_APP_ID", ""),
|
|
AppKey: getEnv("QQ_APP_KEY", ""),
|
|
AppSecret: getEnv("QQ_APP_SECRET", ""),
|
|
RedirectURI: getEnv("QQ_REDIRECT_URI", ""),
|
|
AuthURL: "https://graph.qq.com/oauth2.0/authorize",
|
|
TokenURL: "https://graph.qq.com/oauth2.0/token",
|
|
OpenIDURL: "https://graph.qq.com/oauth2.0/me",
|
|
UserInfoURL: "https://graph.qq.com/user/get_user_info",
|
|
},
|
|
Weibo: WeiboOAuthConfig{
|
|
Enabled: getEnvBool("WEIBO_OAUTH_ENABLED", false),
|
|
AppKey: getEnv("WEIBO_APP_KEY", ""),
|
|
AppSecret: getEnv("WEIBO_APP_SECRET", ""),
|
|
RedirectURI: getEnv("WEIBO_REDIRECT_URI", ""),
|
|
AuthURL: "https://api.weibo.com/oauth2/authorize",
|
|
TokenURL: "https://api.weibo.com/oauth2/access_token",
|
|
UserInfoURL: "https://api.weibo.com/2/users/show.json",
|
|
},
|
|
Twitter: TwitterOAuthConfig{
|
|
Enabled: getEnvBool("TWITTER_OAUTH_ENABLED", false),
|
|
ClientID: getEnv("TWITTER_CLIENT_ID", ""),
|
|
ClientSecret: getEnv("TWITTER_CLIENT_SECRET", ""),
|
|
AuthURL: "https://twitter.com/i/oauth2/authorize",
|
|
TokenURL: "https://api.twitter.com/2/oauth2/token",
|
|
UserInfoURL: "https://api.twitter.com/2/users/me",
|
|
},
|
|
}
|
|
}
|
|
|
|
// GetOAuthConfig 获取OAuth配置
|
|
func GetOAuthConfig() *OAuthConfigYAML {
|
|
if oauthConfig == nil {
|
|
_, _ = LoadOAuthConfig("")
|
|
}
|
|
return oauthConfig
|
|
}
|
|
|
|
// getEnv 获取环境变量
|
|
func getEnv(key, defaultValue string) string {
|
|
if value := os.Getenv(key); value != "" {
|
|
return value
|
|
}
|
|
return defaultValue
|
|
}
|
|
|
|
// getEnvBool 获取布尔型环境变量
|
|
func getEnvBool(key string, defaultValue bool) bool {
|
|
if value := os.Getenv(key); value != "" {
|
|
return strings.ToLower(value) == "true" || value == "1"
|
|
}
|
|
return defaultValue
|
|
}
|