1
18
19
20 package oauth
21
22 import (
23 "context"
24 "fmt"
25 "net/url"
26 "os"
27 "sync"
28
29 "golang.org/x/oauth2"
30 "golang.org/x/oauth2/google"
31 "golang.org/x/oauth2/jwt"
32 "google.golang.org/grpc/credentials"
33 )
34
35
36 type TokenSource struct {
37 oauth2.TokenSource
38 }
39
40
41 func (ts TokenSource) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
42 token, err := ts.Token()
43 if err != nil {
44 return nil, err
45 }
46 ri, _ := credentials.RequestInfoFromContext(ctx)
47 if err = credentials.CheckSecurityLevel(ri.AuthInfo, credentials.PrivacyAndIntegrity); err != nil {
48 return nil, fmt.Errorf("unable to transfer TokenSource PerRPCCredentials: %v", err)
49 }
50 return map[string]string{
51 "authorization": token.Type() + " " + token.AccessToken,
52 }, nil
53 }
54
55
56 func (ts TokenSource) RequireTransportSecurity() bool {
57 return true
58 }
59
60
61 func removeServiceNameFromJWTURI(uri string) (string, error) {
62 parsed, err := url.Parse(uri)
63 if err != nil {
64 return "", err
65 }
66 parsed.Path = "/"
67 return parsed.String(), nil
68 }
69
70 type jwtAccess struct {
71 jsonKey []byte
72 }
73
74
75 func NewJWTAccessFromFile(keyFile string) (credentials.PerRPCCredentials, error) {
76 jsonKey, err := os.ReadFile(keyFile)
77 if err != nil {
78 return nil, fmt.Errorf("credentials: failed to read the service account key file: %v", err)
79 }
80 return NewJWTAccessFromKey(jsonKey)
81 }
82
83
84 func NewJWTAccessFromKey(jsonKey []byte) (credentials.PerRPCCredentials, error) {
85 return jwtAccess{jsonKey}, nil
86 }
87
88 func (j jwtAccess) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
89
90
91 aud, err := removeServiceNameFromJWTURI(uri[0])
92 if err != nil {
93 return nil, err
94 }
95
96
97 ts, err := google.JWTAccessTokenSourceFromJSON(j.jsonKey, aud)
98 if err != nil {
99 return nil, err
100 }
101 token, err := ts.Token()
102 if err != nil {
103 return nil, err
104 }
105 ri, _ := credentials.RequestInfoFromContext(ctx)
106 if err = credentials.CheckSecurityLevel(ri.AuthInfo, credentials.PrivacyAndIntegrity); err != nil {
107 return nil, fmt.Errorf("unable to transfer jwtAccess PerRPCCredentials: %v", err)
108 }
109 return map[string]string{
110 "authorization": token.Type() + " " + token.AccessToken,
111 }, nil
112 }
113
114 func (j jwtAccess) RequireTransportSecurity() bool {
115 return true
116 }
117
118
119 type oauthAccess struct {
120 token oauth2.Token
121 }
122
123
124
125
126 func NewOauthAccess(token *oauth2.Token) credentials.PerRPCCredentials {
127 return oauthAccess{token: *token}
128 }
129
130 func (oa oauthAccess) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
131 ri, _ := credentials.RequestInfoFromContext(ctx)
132 if err := credentials.CheckSecurityLevel(ri.AuthInfo, credentials.PrivacyAndIntegrity); err != nil {
133 return nil, fmt.Errorf("unable to transfer oauthAccess PerRPCCredentials: %v", err)
134 }
135 return map[string]string{
136 "authorization": oa.token.Type() + " " + oa.token.AccessToken,
137 }, nil
138 }
139
140 func (oa oauthAccess) RequireTransportSecurity() bool {
141 return true
142 }
143
144
145
146
147
148 func NewComputeEngine() credentials.PerRPCCredentials {
149 return TokenSource{google.ComputeTokenSource("")}
150 }
151
152
153 type serviceAccount struct {
154 mu sync.Mutex
155 config *jwt.Config
156 t *oauth2.Token
157 }
158
159 func (s *serviceAccount) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
160 s.mu.Lock()
161 defer s.mu.Unlock()
162 if !s.t.Valid() {
163 var err error
164 s.t, err = s.config.TokenSource(ctx).Token()
165 if err != nil {
166 return nil, err
167 }
168 }
169 ri, _ := credentials.RequestInfoFromContext(ctx)
170 if err := credentials.CheckSecurityLevel(ri.AuthInfo, credentials.PrivacyAndIntegrity); err != nil {
171 return nil, fmt.Errorf("unable to transfer serviceAccount PerRPCCredentials: %v", err)
172 }
173 return map[string]string{
174 "authorization": s.t.Type() + " " + s.t.AccessToken,
175 }, nil
176 }
177
178 func (s *serviceAccount) RequireTransportSecurity() bool {
179 return true
180 }
181
182
183
184 func NewServiceAccountFromKey(jsonKey []byte, scope ...string) (credentials.PerRPCCredentials, error) {
185 config, err := google.JWTConfigFromJSON(jsonKey, scope...)
186 if err != nil {
187 return nil, err
188 }
189 return &serviceAccount{config: config}, nil
190 }
191
192
193
194 func NewServiceAccountFromFile(keyFile string, scope ...string) (credentials.PerRPCCredentials, error) {
195 jsonKey, err := os.ReadFile(keyFile)
196 if err != nil {
197 return nil, fmt.Errorf("credentials: failed to read the service account key file: %v", err)
198 }
199 return NewServiceAccountFromKey(jsonKey, scope...)
200 }
201
202
203
204 func NewApplicationDefault(ctx context.Context, scope ...string) (credentials.PerRPCCredentials, error) {
205 creds, err := google.FindDefaultCredentials(ctx, scope...)
206 if err != nil {
207 return nil, err
208 }
209
210
211
212
213 if creds.JSON == nil {
214 return TokenSource{creds.TokenSource}, nil
215 }
216
217
218
219
220
221
222
223
224
225
226
227
228 if len(scope) != 0 {
229 return TokenSource{creds.TokenSource}, nil
230 }
231
232
233
234
235
236 if _, err := google.JWTConfigFromJSON(creds.JSON); err != nil {
237
238
239 return TokenSource{creds.TokenSource}, nil
240 }
241
242
243 return NewJWTAccessFromKey(creds.JSON)
244 }
245
View as plain text