Skip to content

Commit

Permalink
Support scope for self-signed JWT (#122)
Browse files Browse the repository at this point in the history
  • Loading branch information
shinfan authored Jul 16, 2021
1 parent f8ab771 commit 937167c
Show file tree
Hide file tree
Showing 18 changed files with 130 additions and 230 deletions.
21 changes: 13 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,14 +261,19 @@ $ oauth2l fetch --type oauth --credentials ~/client_credentials.json --scope clo
#### jwt

When jwt is selected and the json file specified in the `--credentials` option
is a service account key file, a JWT token signed by the service account
private key will be generated. When using this option, no scope parameter is
needed but a single JWT audience must be provided. See how to construct the
audience [here](https://developers.google.com/identity/protocols/OAuth2ServiceAccount#jwt-auth).

```bash
$ oauth2l fetch --type jwt --credentials ~/service_account.json --audience https://pubsub.googleapis.com/
```
is a service account key file, a JWT token signed by the service account private
key will be generated. Either `--scope` or `--audience` must be specified for
this option. See how to construct the audience [here](https://developers.google.com/identity/protocols/OAuth2ServiceAccount#jwt-auth).

- With scope:
```bash
$ oauth2l fetch --type jwt --credentials ~/client_credentials.json --scope cloud-platform
```

- With audience:
```bash
$ oauth2l fetch --type jwt --credentials ~/service_account.json --audience https://pubsub.googleapis.com/
```

#### sso

Expand Down
9 changes: 1 addition & 8 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,6 @@ module github.com/google/oauth2l
go 1.13

require (
cloud.google.com/go v0.65.0 // indirect
github.com/golang/protobuf v1.4.2 // indirect
github.com/jessevdk/go-flags v1.4.0
github.com/wora/protorpc v0.0.0-20180730014223-ae9256a051d8 // indirect
golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect
golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c
google.golang.org/appengine v1.6.6 // indirect
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987 // indirect
google.golang.org/grpc v1.31.0 // indirect
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914
)
172 changes: 4 additions & 168 deletions go.sum

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion integration/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ func TestCLI(t *testing.T) {
{
"fetch; jwt; no audience",
[]string{"fetch", "--type", "jwt"},
"no-audience.golden",
"no-scope-or-audience.golden",
false,
},
{
Expand Down
1 change: 0 additions & 1 deletion integration/golden/no-audience.golden

This file was deleted.

1 change: 1 addition & 0 deletions integration/golden/no-scope-or-audience.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
neither audience nor scope is provided
12 changes: 5 additions & 7 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ func main() {

// Configure GUAC settings based on authType.
var settings *util.Settings
if authType == "jwt" {
if authType == util.AuthTypeJWT {
json, err := readJSON(credentials)
if err != nil {
fmt.Println("Failed to open file: " + credentials)
Expand All @@ -313,19 +313,16 @@ func main() {
if audience == "" {
if len(remainingArgs) > 0 {
audience = remainingArgs[0]
} else {
fmt.Println("Missing audience argument for JWT")
return
}
}

// JWT flow requires empty Scope.
// Also, JWT currently does not work with STS.
settings = &util.Settings{
AuthType: util.AuthTypeJWT,
CredentialsJSON: json,
Audience: audience,
Scope: scope,
}
} else if authType == "sso" {
} else if authType == util.AuthTypeSSO {
// Fallback to reading email from first remaining arg
argProcessedIndex := 0
if email == "" {
Expand Down Expand Up @@ -380,6 +377,7 @@ func main() {
Sts: sts,
ServiceAccount: serviceAccount,
Email: email,
AuthType: util.AuthTypeOAuth,
}
}

Expand Down
20 changes: 15 additions & 5 deletions util/fetch.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ package util

import (
"context"
"errors"
"fmt"
"strings"

"golang.org/x/oauth2"
Expand All @@ -31,12 +33,15 @@ func newTokenSource(ctx context.Context, settings *Settings) (*oauth2.TokenSourc
var err error
if settings == nil {
ts, err = google.DefaultTokenSource(ctx, DefaultScope)
} else if settings.APIKey != "" {
} else if settings.GetAuthType() == AuthTypeAPIKey {
return nil, nil
} else if settings.Scope != "" {
} else if settings.GetAuthType() == AuthTypeOAuth {
ts, err = OAuthJSONTokenSource(ctx, settings)
} else {
} else if settings.GetAuthType() == AuthTypeJWT {
ts, err = JWTTokenSource(ctx, settings)
} else {
return nil, fmt.Errorf(
"Unsupported authentcation method: %s", settings.GetAuthType())
}
if err != nil {
return nil, err
Expand Down Expand Up @@ -76,8 +81,13 @@ func JWTTokenSource(ctx context.Context, settings *Settings) (oauth2.TokenSource
if err != nil {
return nil, err
}
ts, err := google.JWTAccessTokenSourceFromJSON(creds.JSON, settings.Audience)
return ts, err
if settings.Audience != "" {
return google.JWTAccessTokenSourceFromJSON(creds.JSON, settings.Audience)
} else if settings.Scope != "" {
return google.JWTAccessTokenSourceWithScope(creds.JSON, settings.Scope)
} else {
return nil, errors.New("neither audience nor scope is provided")
}
}

// FindJSONCredentials obtains credentials from settings or Application Default Credentials
Expand Down
21 changes: 13 additions & 8 deletions util/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,18 @@ import (
"golang.org/x/oauth2/authhandler"
)

var MethodOAuth = "oauth"
var MethodJWT = "jwt"
var MethodAPIKey = "apikey"
var AuthTypeOAuth = "oauth"
var AuthTypeJWT = "jwt"
var AuthTypeAPIKey = "apikey"
var AuthTypeSSO = "sso"

// An extensible structure that holds the credentials for
// Google API authentication.
type Settings struct {
// The JSON credentials content downloaded from Google Cloud Console.
CredentialsJSON string
// The authentication type.
AuthType string
// If specified, use OAuth. Otherwise, JWT.
Scope string
// The audience field for JWT auth
Expand All @@ -52,11 +55,13 @@ type Settings struct {
ServiceAccount string
}

func (s Settings) AuthMethod() string {
if s.APIKey != "" {
return MethodAPIKey
func (s Settings) GetAuthType() string {
if s.AuthType != "" {
return s.AuthType
} else if s.APIKey != "" {
return AuthTypeAPIKey
} else if s.Scope != "" {
return MethodOAuth
return AuthTypeOAuth
}
return MethodJWT
return AuthTypeJWT
}
2 changes: 1 addition & 1 deletion vendor/github.com/jessevdk/go-flags/completion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions vendor/golang.org/x/oauth2/google/doc.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 32 additions & 5 deletions vendor/golang.org/x/oauth2/google/jwt.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions vendor/google.golang.org/protobuf/internal/impl/merge_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 937167c

Please sign in to comment.