a685e3fc98
Vndr has a simpler configuration and allows pointing to forked packages. Additionally other docker projects are now using vndr making vendoring in distribution more consistent. Updates letsencrypt to use fork. No longer uses sub-vendored packages. Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
146 lines
4.7 KiB
Go
146 lines
4.7 KiB
Go
// Copyright 2014 The Go 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 google provides support for making OAuth2 authorized and
|
|
// authenticated HTTP requests to Google APIs.
|
|
// It supports the Web server flow, client-side credentials, service accounts,
|
|
// Google Compute Engine service accounts, and Google App Engine service
|
|
// accounts.
|
|
//
|
|
// For more information, please read
|
|
// https://developers.google.com/accounts/docs/OAuth2
|
|
// and
|
|
// https://developers.google.com/accounts/docs/application-default-credentials.
|
|
package google // import "golang.org/x/oauth2/google"
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"golang.org/x/oauth2"
|
|
"golang.org/x/oauth2/jwt"
|
|
"google.golang.org/cloud/compute/metadata"
|
|
)
|
|
|
|
// Endpoint is Google's OAuth 2.0 endpoint.
|
|
var Endpoint = oauth2.Endpoint{
|
|
AuthURL: "https://accounts.google.com/o/oauth2/auth",
|
|
TokenURL: "https://accounts.google.com/o/oauth2/token",
|
|
}
|
|
|
|
// JWTTokenURL is Google's OAuth 2.0 token URL to use with the JWT flow.
|
|
const JWTTokenURL = "https://accounts.google.com/o/oauth2/token"
|
|
|
|
// ConfigFromJSON uses a Google Developers Console client_credentials.json
|
|
// file to construct a config.
|
|
// client_credentials.json can be downloadable from https://console.developers.google.com,
|
|
// under "APIs & Auth" > "Credentials". Download the Web application credentials in the
|
|
// JSON format and provide the contents of the file as jsonKey.
|
|
func ConfigFromJSON(jsonKey []byte, scope ...string) (*oauth2.Config, error) {
|
|
type cred struct {
|
|
ClientID string `json:"client_id"`
|
|
ClientSecret string `json:"client_secret"`
|
|
RedirectURIs []string `json:"redirect_uris"`
|
|
AuthURI string `json:"auth_uri"`
|
|
TokenURI string `json:"token_uri"`
|
|
}
|
|
var j struct {
|
|
Web *cred `json:"web"`
|
|
Installed *cred `json:"installed"`
|
|
}
|
|
if err := json.Unmarshal(jsonKey, &j); err != nil {
|
|
return nil, err
|
|
}
|
|
var c *cred
|
|
switch {
|
|
case j.Web != nil:
|
|
c = j.Web
|
|
case j.Installed != nil:
|
|
c = j.Installed
|
|
default:
|
|
return nil, fmt.Errorf("oauth2/google: no credentials found")
|
|
}
|
|
if len(c.RedirectURIs) < 1 {
|
|
return nil, errors.New("oauth2/google: missing redirect URL in the client_credentials.json")
|
|
}
|
|
return &oauth2.Config{
|
|
ClientID: c.ClientID,
|
|
ClientSecret: c.ClientSecret,
|
|
RedirectURL: c.RedirectURIs[0],
|
|
Scopes: scope,
|
|
Endpoint: oauth2.Endpoint{
|
|
AuthURL: c.AuthURI,
|
|
TokenURL: c.TokenURI,
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
// JWTConfigFromJSON uses a Google Developers service account JSON key file to read
|
|
// the credentials that authorize and authenticate the requests.
|
|
// Create a service account on "Credentials" page under "APIs & Auth" for your
|
|
// project at https://console.developers.google.com to download a JSON key file.
|
|
func JWTConfigFromJSON(jsonKey []byte, scope ...string) (*jwt.Config, error) {
|
|
var key struct {
|
|
Email string `json:"client_email"`
|
|
PrivateKey string `json:"private_key"`
|
|
}
|
|
if err := json.Unmarshal(jsonKey, &key); err != nil {
|
|
return nil, err
|
|
}
|
|
return &jwt.Config{
|
|
Email: key.Email,
|
|
PrivateKey: []byte(key.PrivateKey),
|
|
Scopes: scope,
|
|
TokenURL: JWTTokenURL,
|
|
}, nil
|
|
}
|
|
|
|
// ComputeTokenSource returns a token source that fetches access tokens
|
|
// from Google Compute Engine (GCE)'s metadata server. It's only valid to use
|
|
// this token source if your program is running on a GCE instance.
|
|
// If no account is specified, "default" is used.
|
|
// Further information about retrieving access tokens from the GCE metadata
|
|
// server can be found at https://cloud.google.com/compute/docs/authentication.
|
|
func ComputeTokenSource(account string) oauth2.TokenSource {
|
|
return oauth2.ReuseTokenSource(nil, computeSource{account: account})
|
|
}
|
|
|
|
type computeSource struct {
|
|
account string
|
|
}
|
|
|
|
func (cs computeSource) Token() (*oauth2.Token, error) {
|
|
if !metadata.OnGCE() {
|
|
return nil, errors.New("oauth2/google: can't get a token from the metadata service; not running on GCE")
|
|
}
|
|
acct := cs.account
|
|
if acct == "" {
|
|
acct = "default"
|
|
}
|
|
tokenJSON, err := metadata.Get("instance/service-accounts/" + acct + "/token")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var res struct {
|
|
AccessToken string `json:"access_token"`
|
|
ExpiresInSec int `json:"expires_in"`
|
|
TokenType string `json:"token_type"`
|
|
}
|
|
err = json.NewDecoder(strings.NewReader(tokenJSON)).Decode(&res)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("oauth2/google: invalid token JSON from metadata: %v", err)
|
|
}
|
|
if res.ExpiresInSec == 0 || res.AccessToken == "" {
|
|
return nil, fmt.Errorf("oauth2/google: incomplete token received from metadata")
|
|
}
|
|
return &oauth2.Token{
|
|
AccessToken: res.AccessToken,
|
|
TokenType: res.TokenType,
|
|
Expiry: time.Now().Add(time.Duration(res.ExpiresInSec) * time.Second),
|
|
}, nil
|
|
}
|