120 lines
3.1 KiB
Go
120 lines
3.1 KiB
Go
package oauth
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
|
|
"golang.org/x/oauth2"
|
|
|
|
"base/config"
|
|
|
|
"base/internal/pkg/oauth/github"
|
|
"base/internal/pkg/oauth/google"
|
|
"base/internal/pkg/oauth/linkedin"
|
|
"base/internal/pkg/oauth/mock"
|
|
"base/internal/pkg/oauth/types"
|
|
)
|
|
|
|
// Token is an alias for types.Token for backward compatibility
|
|
type Token = types.Token
|
|
|
|
type OAuth struct {
|
|
google types.Oauth
|
|
linkedin types.Oauth
|
|
github types.Oauth
|
|
mock types.Oauth
|
|
}
|
|
|
|
type Config struct {
|
|
GoogleConfig oauth2.Config
|
|
GitHubConfig oauth2.Config
|
|
LinkedinConfig oauth2.Config
|
|
}
|
|
|
|
func New(cfg *config.AppConfig) OAuth {
|
|
oauthConfig := Config{
|
|
GoogleConfig: oauth2.Config{
|
|
ClientID: cfg.OAuth.Google.ClientID,
|
|
ClientSecret: cfg.OAuth.Google.ClientSecret,
|
|
RedirectURL: cfg.OAuth.Google.RedirectURL,
|
|
Scopes: cfg.OAuth.Google.Scopes,
|
|
},
|
|
GitHubConfig: oauth2.Config{
|
|
ClientID: cfg.OAuth.GitHub.ClientID,
|
|
ClientSecret: cfg.OAuth.GitHub.ClientSecret,
|
|
RedirectURL: cfg.OAuth.GitHub.RedirectURL,
|
|
Scopes: cfg.OAuth.GitHub.Scopes,
|
|
},
|
|
LinkedinConfig: oauth2.Config{
|
|
ClientID: cfg.OAuth.LinkedIn.ClientID,
|
|
ClientSecret: cfg.OAuth.LinkedIn.ClientSecret,
|
|
RedirectURL: cfg.OAuth.LinkedIn.RedirectURL,
|
|
Scopes: cfg.OAuth.LinkedIn.Scopes,
|
|
},
|
|
}
|
|
|
|
o := OAuth{
|
|
google: google.New(oauthConfig.GoogleConfig),
|
|
linkedin: linkedin.New(oauthConfig.LinkedinConfig),
|
|
github: github.New(oauthConfig.GitHubConfig),
|
|
}
|
|
|
|
if cfg.OAuth.Mock.Enabled && strings.TrimSpace(cfg.OAuth.Mock.BaseURL) != "" {
|
|
baseURL := strings.TrimSuffix(strings.TrimSpace(cfg.OAuth.Mock.BaseURL), "/")
|
|
mockConfig := oauth2.Config{
|
|
ClientID: cfg.OAuth.Mock.ClientID,
|
|
ClientSecret: cfg.OAuth.Mock.ClientSecret,
|
|
RedirectURL: cfg.OAuth.Mock.RedirectURL,
|
|
Scopes: cfg.OAuth.Mock.Scopes,
|
|
}
|
|
if mockConfig.ClientID == "" {
|
|
mockConfig.ClientID = "mock-client"
|
|
}
|
|
if mockConfig.ClientSecret == "" {
|
|
mockConfig.ClientSecret = "mock-secret"
|
|
}
|
|
if mockConfig.RedirectURL == "" {
|
|
mockConfig.RedirectURL = "http://localhost:3000/auth/callback"
|
|
}
|
|
o.mock = mock.New(mockConfig, baseURL)
|
|
}
|
|
return o
|
|
}
|
|
|
|
func (a OAuth) Client(provider Provider) types.Oauth {
|
|
switch provider {
|
|
case Google:
|
|
return a.google
|
|
case Linkedin:
|
|
return a.linkedin
|
|
case GitHub:
|
|
return a.github
|
|
case Mock:
|
|
if a.mock != nil {
|
|
return a.mock
|
|
}
|
|
return disabledMockClient{}
|
|
default:
|
|
return a.google
|
|
}
|
|
}
|
|
|
|
// ErrMockNotEnabled is returned when mock provider is used but not configured
|
|
var ErrMockNotEnabled = errors.New("oauth mock is not enabled - set oauth.mock.enabled=true and oauth.mock.base_url")
|
|
|
|
// disabledMockClient is used when mock is requested but not configured
|
|
type disabledMockClient struct{}
|
|
|
|
func (disabledMockClient) GetConsentAuthUrl(_ context.Context, _ string) string {
|
|
panic("oauth mock is not enabled - set oauth.mock.enabled=true and oauth.mock.base_url")
|
|
}
|
|
|
|
func (disabledMockClient) ExchangeCodeWithToken(context.Context, string) (*types.Token, error) {
|
|
return nil, ErrMockNotEnabled
|
|
}
|
|
|
|
func (disabledMockClient) GetUserInfo(context.Context, string, string) (types.UserInfo, error) {
|
|
return nil, ErrMockNotEnabled
|
|
}
|