Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

all: use OAuth2 refresh token in storage config #1

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 4 additions & 11 deletions cloud/storage/dropbox/dropbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,22 @@ import (
"net/http"
"strings"

"dropbox.upspin.io/oauth2"
"upspin.io/cloud/storage"
"upspin.io/errors"
"upspin.io/upspin"
)

// apiToken is the key for the dial options in the storage.Storage interface.
const apiToken = "token"

// New initializes a Storage implementation that stores data to Dropbox.
func New(opts *storage.Opts) (storage.Storage, error) {
const op errors.Op = "cloud/storage/dropbox.New"

tok, ok := opts.Opts[apiToken]
token, ok := opts.Opts["refresh_token"]
if !ok {
return nil, errors.E(op, errors.Invalid, errors.Errorf("%q option is required", apiToken))
return nil, errors.E(op, errors.Invalid, errors.Errorf("refresh_token option is required"))
}

return &dropboxImpl{
client: http.DefaultClient,
token: tok,
}, nil
return &dropboxImpl{oauth2.Client(token)}, nil
}

func init() {
Expand All @@ -44,7 +39,6 @@ func init() {
// dropboxImpl is an implementation of Storage that connects to a Dropbox backend.
type dropboxImpl struct {
client *http.Client
token string
}

var (
Expand Down Expand Up @@ -216,7 +210,6 @@ func (d *dropboxImpl) newRequest(path string, body io.Reader, arg string) (*http
return nil, err
}

req.Header.Add("Authorization", "Bearer "+d.token)
req.Header.Add("Content-Type", "application/octet-stream")

if arg != "" {
Expand Down
31 changes: 17 additions & 14 deletions cloud/storage/dropbox/dropbox_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (

"golang.org/x/oauth2"

dboauth2 "dropbox.upspin.io/oauth2"
"upspin.io/cloud/storage"
"upspin.io/upspin"
)
Expand All @@ -30,6 +31,17 @@ var (
useDropbox = flag.Bool("use_dropbox", false, "enable to run dropbox tests; requires authentication code")
)

func init() {
dboauth2.Config = &oauth2.Config{
ClientID: "ufhy41x7g4obzqz",
ClientSecret: "vuhgmucmxm93dp5",
Endpoint: oauth2.Endpoint{
AuthURL: "https://www.dropbox.com/oauth2/authorize",
TokenURL: "https://api.dropboxapi.com/oauth2/token",
},
}
}

func TestList(t *testing.T) {
ls, ok := client.(storage.Lister)
if !ok {
Expand Down Expand Up @@ -139,7 +151,7 @@ func TestMain(m *testing.M) {
cloud/storage/dropbox: skipping test as it requires Dropbox access. To enable this test,
on the first run get an authentication code by visiting:

https://www.dropbox.com/oauth2/authorize?client_id=ufhy41x7g4obzqz&response_type=code
https://www.dropbox.com/oauth2/authorize?client_id=ufhy41x7g4obzqz&response_type=code&token_access_type=offline

Copy the code and pass it by the -code flag. This will get an oAuth2 access token, store
it and reuse it in successive test calls.
Expand All @@ -155,7 +167,7 @@ it and reuse it in successive test calls.

// Create client that writes to your Dropbox.
client, err = storage.Dial("Dropbox",
storage.WithKeyValue("token", t))
storage.WithKeyValue("refresh_token", t))
if err != nil {
log.Fatalf("cloud/storage/dropbox: couldn't set up client: %v", err)
}
Expand All @@ -173,23 +185,14 @@ func token() (string, error) {
return string(token), nil
}

conf := &oauth2.Config{
ClientID: "ufhy41x7g4obzqz",
ClientSecret: "vuhgmucmxm93dp5",
Endpoint: oauth2.Endpoint{
AuthURL: "https://www.dropbox.com/oauth2/authorize",
TokenURL: "https://api.dropboxapi.com/oauth2/token",
},
}

tok, err := conf.Exchange(oauth2.NoContext, *authCode)
tok, err := dboauth2.Exchange(*authCode)
if err != nil {
return "", err
}

if err := ioutil.WriteFile(tokenFile, []byte(tok.AccessToken), 0600); err != nil {
if err := ioutil.WriteFile(tokenFile, []byte(tok), 0600); err != nil {
return "", err
}

return tok.AccessToken, nil
return tok, nil
}
29 changes: 7 additions & 22 deletions cmd/upspin-setupstorage-dropbox/setupstorage.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ import (
"os"
"path/filepath"

"golang.org/x/oauth2"

"dropbox.upspin.io/oauth2"
"upspin.io/subcmd"
)

Expand All @@ -33,7 +32,7 @@ the specified authorization code to access your Dropbox.

Before running this command, you must obtain an authorization code:

1. Go to https://www.dropbox.com/oauth2/authorize?client_id=wt1281n3q768jj3&response_type=code
1. Go to https://www.dropbox.com/oauth2/authorize?client_id=wt1281n3q768jj3&response_type=code&token_access_type=offline
2. Click "Allow" (you might have to log in first).
3. Copy the authorization code
4. Run setupstorage-dropbox -domain <domain.tld> <authorization_code>
Expand Down Expand Up @@ -65,32 +64,18 @@ func main() {

cfgPath := filepath.Join(*where, *domain)
cfg := s.ReadServerConfig(cfgPath)
token, err := oauth2.Exchange(authCode)
if err != nil {
s.Exit(err)
}

cfg.StoreConfig = []string{
"backend=Dropbox",
"token=" + s.token(authCode),
"refresh_token=" + token,
}
s.WriteServerConfig(cfgPath, cfg)

fmt.Fprintf(os.Stderr, "You should now deploy the upspinserver binary and run 'upspin setupserver'.\n")

s.ExitNow()
}

func (s *state) token(code string) string {
conf := &oauth2.Config{
ClientID: "wt1281n3q768jj3",
ClientSecret: "blk944sx4oyf6aq",
Endpoint: oauth2.Endpoint{
AuthURL: "https://www.dropbox.com/oauth2/authorize",
TokenURL: "https://api.dropboxapi.com/oauth2/token",
},
}

token, err := conf.Exchange(oauth2.NoContext, code)
if err != nil {
s.Exit(err)
}

return token.AccessToken
}
40 changes: 40 additions & 0 deletions oauth2/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright 2017 The Upspin Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package oauth2

import (
"context"
"net/http"

"golang.org/x/oauth2"
)

// The default Dropbox client configuration; this client uses the `Apps/upspin/`
// folder in the linked Dropbox account for storage.
var Config = &oauth2.Config{
ClientID: "wt1281n3q768jj3",
ClientSecret: "blk944sx4oyf6aq",
Endpoint: oauth2.Endpoint{
AuthURL: "https://www.dropbox.com/oauth2/authorize",
TokenURL: "https://api.dropboxapi.com/oauth2/token",
},
}

// Client returns an HTTP client that populates the Authorization header of all
// requests with an access token.
func Client(refreshToken string) *http.Client {
token := oauth2.Token{RefreshToken: refreshToken}
return Config.Client(context.Background(), &token)
}

// Exchange converts the authorization code into a refresh token.
func Exchange(authCode string) (string, error) {
token, err := Config.Exchange(context.Background(), authCode)
if err != nil {
return "", err
}

return token.RefreshToken, nil
}