1/* 2 * 3 * Copyright 2015, Google Inc. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * * Redistributions in binary form must reproduce the above 13 * copyright notice, this list of conditions and the following disclaimer 14 * in the documentation and/or other materials provided with the 15 * distribution. 16 * * Neither the name of Google Inc. nor the names of its 17 * contributors may be used to endorse or promote products derived from 18 * this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * 32 */ 33 34// Package oauth implements gRPC credentials using OAuth. 35package oauth 36 37import ( 38 "fmt" 39 "io/ioutil" 40 41 "golang.org/x/net/context" 42 "golang.org/x/oauth2" 43 "golang.org/x/oauth2/google" 44 "golang.org/x/oauth2/jwt" 45 "google.golang.org/grpc/credentials" 46) 47 48// TokenSource supplies credentials from an oauth2.TokenSource. 49type TokenSource struct { 50 oauth2.TokenSource 51} 52 53// GetRequestMetadata gets the request metadata as a map from a TokenSource. 54func (ts TokenSource) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { 55 token, err := ts.Token() 56 if err != nil { 57 return nil, err 58 } 59 return map[string]string{ 60 "authorization": token.TokenType + " " + token.AccessToken, 61 }, nil 62} 63 64func (ts TokenSource) RequireTransportSecurity() bool { 65 return true 66} 67 68type jwtAccess struct { 69 jsonKey []byte 70} 71 72func NewJWTAccessFromFile(keyFile string) (credentials.Credentials, error) { 73 jsonKey, err := ioutil.ReadFile(keyFile) 74 if err != nil { 75 return nil, fmt.Errorf("credentials: failed to read the service account key file: %v", err) 76 } 77 return NewJWTAccessFromKey(jsonKey) 78} 79 80func NewJWTAccessFromKey(jsonKey []byte) (credentials.Credentials, error) { 81 return jwtAccess{jsonKey}, nil 82} 83 84func (j jwtAccess) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { 85 ts, err := google.JWTAccessTokenSourceFromJSON(j.jsonKey, uri[0]) 86 if err != nil { 87 return nil, err 88 } 89 token, err := ts.Token() 90 if err != nil { 91 return nil, err 92 } 93 return map[string]string{ 94 "authorization": token.TokenType + " " + token.AccessToken, 95 }, nil 96} 97 98func (j jwtAccess) RequireTransportSecurity() bool { 99 return true 100} 101 102// oauthAccess supplies credentials from a given token. 103type oauthAccess struct { 104 token oauth2.Token 105} 106 107// NewOauthAccess constructs the credentials using a given token. 108func NewOauthAccess(token *oauth2.Token) credentials.Credentials { 109 return oauthAccess{token: *token} 110} 111 112func (oa oauthAccess) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { 113 return map[string]string{ 114 "authorization": oa.token.TokenType + " " + oa.token.AccessToken, 115 }, nil 116} 117 118func (oa oauthAccess) RequireTransportSecurity() bool { 119 return true 120} 121 122// NewComputeEngine constructs the credentials that fetches access tokens from 123// Google Compute Engine (GCE)'s metadata server. It is only valid to use this 124// if your program is running on a GCE instance. 125// TODO(dsymonds): Deprecate and remove this. 126func NewComputeEngine() credentials.Credentials { 127 return TokenSource{google.ComputeTokenSource("")} 128} 129 130// serviceAccount represents credentials via JWT signing key. 131type serviceAccount struct { 132 config *jwt.Config 133} 134 135func (s serviceAccount) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { 136 token, err := s.config.TokenSource(ctx).Token() 137 if err != nil { 138 return nil, err 139 } 140 return map[string]string{ 141 "authorization": token.TokenType + " " + token.AccessToken, 142 }, nil 143} 144 145func (s serviceAccount) RequireTransportSecurity() bool { 146 return true 147} 148 149// NewServiceAccountFromKey constructs the credentials using the JSON key slice 150// from a Google Developers service account. 151func NewServiceAccountFromKey(jsonKey []byte, scope ...string) (credentials.Credentials, error) { 152 config, err := google.JWTConfigFromJSON(jsonKey, scope...) 153 if err != nil { 154 return nil, err 155 } 156 return serviceAccount{config: config}, nil 157} 158 159// NewServiceAccountFromFile constructs the credentials using the JSON key file 160// of a Google Developers service account. 161func NewServiceAccountFromFile(keyFile string, scope ...string) (credentials.Credentials, error) { 162 jsonKey, err := ioutil.ReadFile(keyFile) 163 if err != nil { 164 return nil, fmt.Errorf("credentials: failed to read the service account key file: %v", err) 165 } 166 return NewServiceAccountFromKey(jsonKey, scope...) 167} 168 169// NewApplicationDefault returns "Application Default Credentials". For more 170// detail, see https://developers.google.com/accounts/docs/application-default-credentials. 171func NewApplicationDefault(ctx context.Context, scope ...string) (credentials.Credentials, error) { 172 t, err := google.DefaultTokenSource(ctx, scope...) 173 if err != nil { 174 return nil, err 175 } 176 return TokenSource{t}, nil 177} 178