github.com/timstclair/heapster@v0.20.0-alpha1/Godeps/_workspace/src/golang.org/x/oauth2/google/google.go (about)

     1  // Copyright 2014 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 provides support for making OAuth2 authorized and
     6  // authenticated HTTP requests to Google APIs.
     7  // It supports the Web server flow, client-side credentials, service accounts,
     8  // Google Compute Engine service accounts, and Google App Engine service
     9  // accounts.
    10  //
    11  // For more information, please read
    12  // https://developers.google.com/accounts/docs/OAuth2
    13  // and
    14  // https://developers.google.com/accounts/docs/application-default-credentials.
    15  package google
    16  
    17  import (
    18  	"encoding/json"
    19  	"errors"
    20  	"fmt"
    21  	"strings"
    22  	"time"
    23  
    24  	"golang.org/x/oauth2"
    25  	"golang.org/x/oauth2/jwt"
    26  	"google.golang.org/cloud/compute/metadata"
    27  )
    28  
    29  // Endpoint is Google's OAuth 2.0 endpoint.
    30  var Endpoint = oauth2.Endpoint{
    31  	AuthURL:  "https://accounts.google.com/o/oauth2/auth",
    32  	TokenURL: "https://accounts.google.com/o/oauth2/token",
    33  }
    34  
    35  // JWTTokenURL is Google's OAuth 2.0 token URL to use with the JWT flow.
    36  const JWTTokenURL = "https://accounts.google.com/o/oauth2/token"
    37  
    38  // ConfigFromJSON uses a Google Developers Console client_credentials.json
    39  // file to construct a config.
    40  // client_credentials.json can be downloadable from https://console.developers.google.com,
    41  // under "APIs & Auth" > "Credentials". Download the Web application credentials in the
    42  // JSON format and provide the contents of the file as jsonKey.
    43  func ConfigFromJSON(jsonKey []byte, scope ...string) (*oauth2.Config, error) {
    44  	type cred struct {
    45  		ClientID     string   `json:"client_id"`
    46  		ClientSecret string   `json:"client_secret"`
    47  		RedirectURIs []string `json:"redirect_uris"`
    48  		AuthURI      string   `json:"auth_uri"`
    49  		TokenURI     string   `json:"token_uri"`
    50  	}
    51  	var j struct {
    52  		Web       *cred `json:"web"`
    53  		Installed *cred `json:"installed"`
    54  	}
    55  	if err := json.Unmarshal(jsonKey, &j); err != nil {
    56  		return nil, err
    57  	}
    58  	var c *cred
    59  	switch {
    60  	case j.Web != nil:
    61  		c = j.Web
    62  	case j.Installed != nil:
    63  		c = j.Installed
    64  	default:
    65  		return nil, fmt.Errorf("oauth2/google: no credentials found")
    66  	}
    67  	if len(c.RedirectURIs) < 1 {
    68  		return nil, errors.New("oauth2/google: missing redirect URL in the client_credentials.json")
    69  	}
    70  	return &oauth2.Config{
    71  		ClientID:     c.ClientID,
    72  		ClientSecret: c.ClientSecret,
    73  		RedirectURL:  c.RedirectURIs[0],
    74  		Scopes:       scope,
    75  		Endpoint: oauth2.Endpoint{
    76  			AuthURL:  c.AuthURI,
    77  			TokenURL: c.TokenURI,
    78  		},
    79  	}, nil
    80  }
    81  
    82  // JWTConfigFromJSON uses a Google Developers service account JSON key file to read
    83  // the credentials that authorize and authenticate the requests.
    84  // Create a service account on "Credentials" page under "APIs & Auth" for your
    85  // project at https://console.developers.google.com to download a JSON key file.
    86  func JWTConfigFromJSON(jsonKey []byte, scope ...string) (*jwt.Config, error) {
    87  	var key struct {
    88  		Email      string `json:"client_email"`
    89  		PrivateKey string `json:"private_key"`
    90  	}
    91  	if err := json.Unmarshal(jsonKey, &key); err != nil {
    92  		return nil, err
    93  	}
    94  	return &jwt.Config{
    95  		Email:      key.Email,
    96  		PrivateKey: []byte(key.PrivateKey),
    97  		Scopes:     scope,
    98  		TokenURL:   JWTTokenURL,
    99  	}, nil
   100  }
   101  
   102  // ComputeTokenSource returns a token source that fetches access tokens
   103  // from Google Compute Engine (GCE)'s metadata server. It's only valid to use
   104  // this token source if your program is running on a GCE instance.
   105  // If no account is specified, "default" is used.
   106  // Further information about retrieving access tokens from the GCE metadata
   107  // server can be found at https://cloud.google.com/compute/docs/authentication.
   108  func ComputeTokenSource(account string) oauth2.TokenSource {
   109  	return oauth2.ReuseTokenSource(nil, computeSource{account: account})
   110  }
   111  
   112  type computeSource struct {
   113  	account string
   114  }
   115  
   116  func (cs computeSource) Token() (*oauth2.Token, error) {
   117  	if !metadata.OnGCE() {
   118  		return nil, errors.New("oauth2/google: can't get a token from the metadata service; not running on GCE")
   119  	}
   120  	acct := cs.account
   121  	if acct == "" {
   122  		acct = "default"
   123  	}
   124  	tokenJSON, err := metadata.Get("instance/service-accounts/" + acct + "/token")
   125  	if err != nil {
   126  		return nil, err
   127  	}
   128  	var res struct {
   129  		AccessToken  string `json:"access_token"`
   130  		ExpiresInSec int    `json:"expires_in"`
   131  		TokenType    string `json:"token_type"`
   132  	}
   133  	err = json.NewDecoder(strings.NewReader(tokenJSON)).Decode(&res)
   134  	if err != nil {
   135  		return nil, fmt.Errorf("oauth2/google: invalid token JSON from metadata: %v", err)
   136  	}
   137  	if res.ExpiresInSec == 0 || res.AccessToken == "" {
   138  		return nil, fmt.Errorf("oauth2/google: incomplete token received from metadata")
   139  	}
   140  	return &oauth2.Token{
   141  		AccessToken: res.AccessToken,
   142  		TokenType:   res.TokenType,
   143  		Expiry:      time.Now().Add(time.Duration(res.ExpiresInSec) * time.Second),
   144  	}, nil
   145  }