diff --git a/google/authhandler.go b/google/authhandler.go index c92bac8..5f78a3e 100644 --- a/google/authhandler.go +++ b/google/authhandler.go @@ -6,18 +6,33 @@ package google import ( "fmt" + + "github.com/google/uuid" ) -const DefaultState = "state" +// RandomAuthorizationState generates a state via UUID generator. +func RandomAuthorizationState() string { + return uuid.New().String() +} -// DefaultAuthorizationHandler is a commandline-based auth handler +// DefaultAuthorizationHandler returns a command line auth handler // that prints the auth URL on the console and prompts the user to // authorize in the browser and paste the auth code back via stdin. -// When using this auth handler, DefaultState must be used. -func DefaultAuthorizationHandler(authCodeUrl string) (string, string, error) { - fmt.Printf("Go to the following link in your browser:\n\n %s\n\n", authCodeUrl) - fmt.Println("Enter verification code: ") +// +// For convenience, this handler returns a pre-configured state +// instead of asking the user to additionally paste the state from +// the auth response. In order for this to work, the state +// configured here should match the one in the oauth2 AuthTokenURL. +func DefaultAuthorizationHandler(state string) AuthorizationHandler { + return func(authCodeURL string) (string, string, error) { + return defaultAuthorizationHandlerHelper(state, authCodeURL) + } +} + +func defaultAuthorizationHandlerHelper(state string, authCodeURL string) (string, string, error) { + fmt.Printf("Go to the following link in your browser:\n\n %s\n\n", authCodeURL) + fmt.Println("Enter authorization code: ") var code string fmt.Scanln(&code) - return code, DefaultState, nil + return code, state, nil } diff --git a/google/google.go b/google/google.go index ebcabe5..ec65bd5 100644 --- a/google/google.go +++ b/google/google.go @@ -220,13 +220,13 @@ type AuthorizationHandler func(string) (string, string, error) // An environment-specific AuthorizationHandler is used to obtain user consent. // Per OAuth protocol, a unique "state" string should be sent and verified // before token exchange to prevent CSRF attacks. -func OAuthClientTokenSource(config oauth2.Config, ctx context.Context, authHandler AuthorizationHandler, state string) oauth2.TokenSource { +func OAuthClientTokenSource(ctx context.Context, config *oauth2.Config, authHandler AuthorizationHandler, state string) oauth2.TokenSource { return oauth2.ReuseTokenSource(nil, oauthClientSource{config: config, ctx: ctx, authHandler: authHandler, state: state}) } type oauthClientSource struct { - config oauth2.Config ctx context.Context + config *oauth2.Config authHandler AuthorizationHandler state string }