Skip to content

Commit 6aa2b5c

Browse files
authored
Bug fixes for JWT with scope and token extras (#124)
1 parent 937167c commit 6aa2b5c

File tree

6 files changed

+58
-39
lines changed

6 files changed

+58
-39
lines changed

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -262,17 +262,17 @@ $ oauth2l fetch --type oauth --credentials ~/client_credentials.json --scope clo
262262

263263
When jwt is selected and the json file specified in the `--credentials` option
264264
is a service account key file, a JWT token signed by the service account private
265-
key will be generated. Either `--scope` or `--audience` must be specified for
265+
key will be generated. Either `--audience` or `--scope` must be specified for
266266
this option. See how to construct the audience [here](https://developers.google.com/identity/protocols/OAuth2ServiceAccount#jwt-auth).
267267

268-
- With scope:
268+
- With audience:
269269
```bash
270-
$ oauth2l fetch --type jwt --credentials ~/client_credentials.json --scope cloud-platform
270+
$ oauth2l fetch --type jwt --credentials ~/service_account.json --audience https://pubsub.googleapis.com/
271271
```
272272

273-
- With audience:
273+
- With scope:
274274
```bash
275-
$ oauth2l fetch --type jwt --credentials ~/service_account.json --audience https://pubsub.googleapis.com/
275+
$ oauth2l fetch --type jwt --credentials ~/service_account.json --scope cloud-platform
276276
```
277277

278278
#### sso
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
neither audience nor scope is provided
1+
Neither audience nor scope argument is provided for JWT

main.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,11 +316,17 @@ func main() {
316316
}
317317
}
318318

319+
scopes := getScopesWithFallback(scope, remainingArgs...)
320+
if audience == "" && len(scopes) < 1 {
321+
fmt.Println("Neither audience nor scope argument is provided for JWT")
322+
return
323+
}
324+
319325
settings = &util.Settings{
320326
AuthType: util.AuthTypeJWT,
321327
CredentialsJSON: json,
322328
Audience: audience,
323-
Scope: scope,
329+
Scope: parseScopes(scopes),
324330
}
325331
} else if authType == util.AuthTypeSSO {
326332
// Fallback to reading email from first remaining arg

util/cache.go

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ func LookupCache(settings *Settings) (*oauth2.Token, error) {
5353
if CacheLocation == "" {
5454
return nil, nil
5555
}
56-
var token oauth2.Token
5756
var cache, err = loadCache()
5857
if err != nil {
5958
return nil, err
@@ -63,11 +62,7 @@ func LookupCache(settings *Settings) (*oauth2.Token, error) {
6362
return nil, err
6463
}
6564
val := cache[string(key)]
66-
err = json.Unmarshal(val, &token)
67-
if err != nil {
68-
return nil, err
69-
}
70-
return &token, nil
65+
return UnmarshalWithExtras(val)
7166
}
7267

7368
func InsertCache(settings *Settings, token *oauth2.Token) error {
@@ -78,7 +73,7 @@ func InsertCache(settings *Settings, token *oauth2.Token) error {
7873
if err != nil {
7974
return err
8075
}
81-
val, err := json.Marshal(*token)
76+
val, err := MarshalWithExtras(token, "")
8277
if err != nil {
8378
return err
8479
}
@@ -155,3 +150,43 @@ func GuessUnixHomeDir() string {
155150
}
156151
return ""
157152
}
153+
154+
// Marshals the given oauth2.Token into a JSON bytearray and include Extra
155+
// fields that normally would be omitted with default marshalling.
156+
func MarshalWithExtras(token *oauth2.Token, indent string) ([]byte, error) {
157+
data, err := json.Marshal(token)
158+
if err != nil {
159+
return nil, err
160+
}
161+
var m map[string]string
162+
err = json.Unmarshal(data, &m)
163+
if err != nil {
164+
return nil, err
165+
}
166+
if token.Extra("issued_token_type") != nil {
167+
m["issued_token_type"] = token.Extra("issued_token_type").(string)
168+
}
169+
if token.Extra("id_token") != nil {
170+
m["id_token"] = token.Extra("id_token").(string)
171+
}
172+
if token.Extra("scope") != nil {
173+
m["scope"] = token.Extra("scope").(string)
174+
}
175+
return json.MarshalIndent(m, "", indent)
176+
}
177+
178+
// Unmarshals the given JSON bytearray into oauth2.Token and include Extra
179+
// fields that normally would be omitted with default unmarshalling.
180+
func UnmarshalWithExtras(data []byte) (*oauth2.Token, error) {
181+
var extra map[string]interface{}
182+
err := json.Unmarshal(data, &extra)
183+
if err != nil {
184+
return nil, err
185+
}
186+
var token oauth2.Token
187+
err = json.Unmarshal(data, &token)
188+
if err != nil {
189+
return nil, err
190+
}
191+
return token.WithExtra(extra), nil
192+
}

util/fetch.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@ func newTokenSource(ctx context.Context, settings *Settings) (*oauth2.TokenSourc
4040
} else if settings.GetAuthType() == AuthTypeJWT {
4141
ts, err = JWTTokenSource(ctx, settings)
4242
} else {
43-
return nil, fmt.Errorf(
44-
"Unsupported authentcation method: %s", settings.GetAuthType())
43+
return nil, fmt.Errorf("Unsupported authentcation method: %s", settings.GetAuthType())
4544
}
4645
if err != nil {
4746
return nil, err
@@ -86,7 +85,7 @@ func JWTTokenSource(ctx context.Context, settings *Settings) (oauth2.TokenSource
8685
} else if settings.Scope != "" {
8786
return google.JWTAccessTokenSourceWithScope(creds.JSON, settings.Scope)
8887
} else {
89-
return nil, errors.New("neither audience nor scope is provided")
88+
return nil, errors.New("Neither audience nor scope is provided for JWTTokenSource")
9089
}
9190
}
9291

util/tasks.go

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -227,27 +227,6 @@ func getCredentialType(creds *google.Credentials) string {
227227
return ""
228228
}
229229

230-
// Marshals the given oauth2.Token into a JSON bytearray and include Extra
231-
// fields that normally would be omitted with default marshalling.
232-
func marshalWithExtras(token *oauth2.Token, indent string) ([]byte, error) {
233-
data, err := json.Marshal(token)
234-
if err != nil {
235-
return nil, err
236-
}
237-
var m map[string]string
238-
err = json.Unmarshal(data, &m)
239-
if err != nil {
240-
return nil, err
241-
}
242-
if token.Extra("issued_token_type") != nil {
243-
m["issued_token_type"] = token.Extra("issued_token_type").(string)
244-
}
245-
if token.Extra("id_token") != nil {
246-
m["id_token"] = token.Extra("id_token").(string)
247-
}
248-
return json.MarshalIndent(m, "", indent)
249-
}
250-
251230
// Prints the token with the specified format.
252231
func printToken(token *oauth2.Token, format string, settings *Settings) {
253232
if token != nil {
@@ -295,7 +274,7 @@ func printHeader(tokenType string, token string) {
295274
}
296275

297276
func printJson(token *oauth2.Token, indent string) {
298-
data, err := marshalWithExtras(token, indent)
277+
data, err := MarshalWithExtras(token, indent)
299278
if err != nil {
300279
log.Fatal(err.Error())
301280
return

0 commit comments

Comments
 (0)