diff --git a/cmd/root.go b/cmd/root.go index 6193806..d8c7362 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -61,12 +61,11 @@ var rootCmd = &cobra.Command{ // Create OAuth config oauthConfig := types.OAuthConfig{ - GithubClientId: config.GithubClientId, - GithubClientSecret: config.GithubClientSecret, - GoogleClientId: config.GoogleClientId, - GoogleClientSecret: config.GoogleClientSecret, - MicrosoftClientId: config.MicrosoftClientId, - MicrosoftClientSecret: config.MicrosoftClientSecret, + GithubClientId: config.GithubClientId, + GithubClientSecret: config.GithubClientSecret, + GoogleClientId: config.GoogleClientId, + GoogleClientSecret: config.GoogleClientSecret, + AppURL: config.AppURL, } // Create auth service @@ -128,8 +127,6 @@ func init() { rootCmd.Flags().String("github-client-secret", "", "Github OAuth client secret.") rootCmd.Flags().String("google-client-id", "", "Google OAuth client ID.") rootCmd.Flags().String("google-client-secret", "", "Google OAuth client secret.") - rootCmd.Flags().String("microsoft-client-id", "", "Microsoft OAuth client ID.") - rootCmd.Flags().String("microsoft-client-secret", "", "Microsoft OAuth client secret.") viper.BindEnv("port", "PORT") viper.BindEnv("address", "ADDRESS") viper.BindEnv("secret", "SECRET") @@ -141,7 +138,5 @@ func init() { viper.BindEnv("github-client-secret", "GITHUB_CLIENT_SECRET") viper.BindEnv("google-client-id", "GOOGLE_CLIENT_ID") viper.BindEnv("google-client-secret", "GOOGLE_CLIENT_SECRET") - viper.BindEnv("microsoft-client-id", "MICROSOFT_CLIENT_ID") - viper.BindEnv("microsoft-client-secret", "MICROSOFT_CLIENT_SECRET") viper.BindPFlags(rootCmd.Flags()) } diff --git a/internal/providers/google.go b/internal/providers/google.go new file mode 100644 index 0000000..1d44e3d --- /dev/null +++ b/internal/providers/google.go @@ -0,0 +1,39 @@ +package providers + +import ( + "encoding/json" + "io" + "net/http" +) + +type GoogleUserinfoResponse struct { + Email string `json:"email"` +} + +func GoogleScopes() []string { + return []string{"https://www.googleapis.com/auth/userinfo.email"} +} + +func GetGoogleEmail(client *http.Client) (string, error) { + res, resErr := client.Get("https://www.googleapis.com/userinfo/v2/me") + + if resErr != nil { + return "", resErr + } + + body, bodyErr := io.ReadAll(res.Body) + + if bodyErr != nil { + return "", bodyErr + } + + var user GoogleUserinfoResponse + + jsonErr := json.Unmarshal(body, &user) + + if jsonErr != nil { + return "", jsonErr + } + + return user.Email, nil +} diff --git a/internal/providers/providers.go b/internal/providers/providers.go index 0e52072..7a1ba81 100644 --- a/internal/providers/providers.go +++ b/internal/providers/providers.go @@ -1,6 +1,7 @@ package providers import ( + "fmt" "tinyauth/internal/oauth" "tinyauth/internal/types" @@ -28,17 +29,31 @@ func (providers *Providers) Init() { providers.Github = oauth.NewOAuth(oauth2.Config{ ClientID: providers.Config.GithubClientId, ClientSecret: providers.Config.GithubClientSecret, + RedirectURL: fmt.Sprintf("%s/api/oauth/callback/github", providers.Config.AppURL), Scopes: GithubScopes(), Endpoint: endpoints.GitHub, }) providers.Github.Init() } + if providers.Config.GoogleClientId != "" && providers.Config.GoogleClientSecret != "" { + log.Info().Msg("Initializing Google OAuth") + providers.Google = oauth.NewOAuth(oauth2.Config{ + ClientID: providers.Config.GoogleClientId, + ClientSecret: providers.Config.GoogleClientSecret, + RedirectURL: fmt.Sprintf("%s/api/oauth/callback/google", providers.Config.AppURL), + Scopes: GoogleScopes(), + Endpoint: endpoints.Google, + }) + providers.Google.Init() + } } func (providers *Providers) GetProvider(provider string) *oauth.OAuth { switch provider { case "github": return providers.Github + case "google": + return providers.Google default: return nil } @@ -56,6 +71,16 @@ func (providers *Providers) GetUser(provider string) (string, error) { return "", emailErr } return email, nil + case "google": + if providers.Google == nil { + return "", nil + } + client := providers.Google.GetClient() + email, emailErr := GetGoogleEmail(client) + if emailErr != nil { + return "", emailErr + } + return email, nil default: return "", nil } @@ -66,5 +91,8 @@ func (provider *Providers) GetConfiguredProviders() []string { if provider.Github != nil { providers = append(providers, "github") } + if provider.Google != nil { + providers = append(providers, "google") + } return providers } diff --git a/internal/types/types.go b/internal/types/types.go index 945a19e..def1f46 100644 --- a/internal/types/types.go +++ b/internal/types/types.go @@ -19,19 +19,17 @@ type User struct { type Users []User type Config struct { - Port int `validate:"number" mapstructure:"port"` - Address string `mapstructure:"address, ip4_addr"` - Secret string `validate:"required,len=32" mapstructure:"secret"` - AppURL string `validate:"required,url" mapstructure:"app-url"` - Users string `mapstructure:"users"` - UsersFile string `mapstructure:"users-file"` - CookieSecure bool `mapstructure:"cookie-secure"` - GithubClientId string `mapstructure:"github-client-id"` - GithubClientSecret string `mapstructure:"github-client-secret"` - GoogleClientId string `mapstructure:"google-client-id"` - GoogleClientSecret string `mapstructure:"google-client-secret"` - MicrosoftClientId string `mapstructure:"microsoft-client-id"` - MicrosoftClientSecret string `mapstructure:"microsoft-client-secret"` + Port int `validate:"number" mapstructure:"port"` + Address string `mapstructure:"address, ip4_addr"` + Secret string `validate:"required,len=32" mapstructure:"secret"` + AppURL string `validate:"required,url" mapstructure:"app-url"` + Users string `mapstructure:"users"` + UsersFile string `mapstructure:"users-file"` + CookieSecure bool `mapstructure:"cookie-secure"` + GithubClientId string `mapstructure:"github-client-id"` + GithubClientSecret string `mapstructure:"github-client-secret"` + GoogleClientId string `mapstructure:"google-client-id"` + GoogleClientSecret string `mapstructure:"google-client-secret"` } type UserContext struct { @@ -50,12 +48,11 @@ type APIConfig struct { } type OAuthConfig struct { - GithubClientId string - GithubClientSecret string - GoogleClientId string - GoogleClientSecret string - MicrosoftClientId string - MicrosoftClientSecret string + GithubClientId string + GithubClientSecret string + GoogleClientId string + GoogleClientSecret string + AppURL string } type OAuthRequest struct {