63 lines
1.4 KiB
Go
63 lines
1.4 KiB
Go
package auth
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
|
|
"golang.org/x/oauth2"
|
|
"golang.org/x/oauth2/google"
|
|
)
|
|
|
|
type OAuthConfig struct {
|
|
*oauth2.Config
|
|
}
|
|
|
|
const (
|
|
base = "https://www.googleapis.com"
|
|
scopeEmail = base + "/auth/userinfo.email"
|
|
scopeProfile = base + "/auth/userinfo.profile"
|
|
)
|
|
|
|
func NewOauthConfig(path string) (OAuthConfig, error) {
|
|
key, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return OAuthConfig{}, fmt.Errorf("could not open file: %w", err)
|
|
}
|
|
|
|
config, err := google.ConfigFromJSON(key, scopeEmail, scopeProfile)
|
|
if err != nil {
|
|
return OAuthConfig{}, fmt.Errorf("could not load config: %w", err)
|
|
}
|
|
|
|
return OAuthConfig{
|
|
Config: config,
|
|
}, nil
|
|
}
|
|
|
|
var ErrInvalidState = errors.New("invalid ouath state provided")
|
|
|
|
type OAuthManager interface {
|
|
Create(callback string) (code string)
|
|
Validate(code string) (callback string, valid bool)
|
|
}
|
|
|
|
func (cfg OAuthConfig) AuthCodeURL(manager OAuthManager, callback string) string {
|
|
state := manager.Create(callback)
|
|
fmt.Printf("state: %v\n", state)
|
|
|
|
return cfg.Config.AuthCodeURL(state, oauth2.AccessTypeOffline)
|
|
}
|
|
|
|
func (cfg OAuthConfig) Exchange(ctx context.Context, manager OAuthManager, state, code string) (string, *oauth2.Token, error) {
|
|
var ok bool
|
|
var callback string
|
|
if callback, ok = manager.Validate(state); !ok {
|
|
return "", nil, ErrInvalidState
|
|
}
|
|
|
|
tk, err := cfg.Config.Exchange(ctx, code, oauth2.AccessTypeOffline)
|
|
return callback, tk, err
|
|
}
|