Skip to content

Commit ceaa866

Browse files
committed
google: Add support for 3-legged-OAuth using OAuth Client ID
Add OAuthClientTokenSource in google/google.go Add DefaultAuthorizationHandler in authhandler.go
1 parent bf48bf1 commit ceaa866

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

google/authhandler.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2020 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package google
6+
7+
import (
8+
"fmt"
9+
)
10+
11+
const DefaultState = "state"
12+
13+
// DefaultAuthorizationHandler is a commandline-based auth handler
14+
// that prints the auth URL on the console and prompts the user to
15+
// authorize in the browser and paste the auth code back via stdin.
16+
// When using this auth handler, DefaultState must be used.
17+
func DefaultAuthorizationHandler(authCodeUrl string) (string, string, error) {
18+
fmt.Printf("Go to the following link in your browser:\n\n %s\n\n", authCodeUrl)
19+
fmt.Println("Enter verification code: ")
20+
var code string
21+
fmt.Scanln(&code)
22+
return code, DefaultState, nil
23+
}

google/google.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,3 +207,38 @@ func (cs computeSource) Token() (*oauth2.Token, error) {
207207
"oauth2.google.serviceAccount": acct,
208208
}), nil
209209
}
210+
211+
// AuthorizationHandler is a 3-legged-OAuth helper that
212+
// prompts the user for OAuth consent at the specified Auth URL
213+
// and returns an auth code and state upon approval.
214+
type AuthorizationHandler func(string) (string, string, error)
215+
216+
// OAuthClientTokenSource returns an oauth2.TokenSource that fetches access tokens
217+
// using 3-legged-OAuth workflow.
218+
// The provided oauth2.Config should be a full configuration containing AuthURL,
219+
// TokenURL, and scope.
220+
// An environment-specific AuthorizationHandler is used to obtain user consent.
221+
// Per OAuth protocol, a unique "state" string should be sent and verified
222+
// before token exchange to prevent CSRF attacks.
223+
func OAuthClientTokenSource(config oauth2.Config, ctx context.Context, authHandler AuthorizationHandler, state string) oauth2.TokenSource {
224+
return oauth2.ReuseTokenSource(nil, oauthClientSource{config: config, ctx: ctx, authHandler: authHandler, state: state})
225+
}
226+
227+
type oauthClientSource struct {
228+
config oauth2.Config
229+
ctx context.Context
230+
authHandler AuthorizationHandler
231+
state string
232+
}
233+
234+
func (ocs oauthClientSource) Token() (*oauth2.Token, error) {
235+
url := ocs.config.AuthCodeURL(ocs.state)
236+
code, state, err := ocs.authHandler(url)
237+
if err != nil {
238+
return nil, err
239+
}
240+
if state == ocs.state {
241+
return ocs.config.Exchange(ocs.ctx, code)
242+
}
243+
return nil, errors.New("State mismatch in OAuth workflow.")
244+
}

0 commit comments

Comments
 (0)