diff --git a/go/oauth2l/main.go b/go/oauth2l/main.go index 1a33a02..e13bda8 100644 --- a/go/oauth2l/main.go +++ b/go/oauth2l/main.go @@ -27,7 +27,7 @@ import ( var ( // Common prefix for google oauth scope scopePrefix = "https://www.googleapis.com/auth/" - cmds = []string{"fetch", "header", "info", "test"} + cmds = []string{"fetch", "header", "info", "test"} ) func help() { @@ -79,6 +79,9 @@ func main() { helpFlag := flagSet.Bool("help", false, "Print help message.") flagSet.BoolVar(helpFlag, "h", false, "") jsonFile := flagSet.String("json", "", "Path to secret json file.") + format := flagSet.String("credentials_format", "bare", "Output format. The supported formats are: "+ + "bare(default), header, json, json_compact, pretty") + flagSet.StringVar(format, "f", "bare", "") jwtFlag := flagSet.Bool("jwt", false, "Use JWT auth flow") ssoFlag := flagSet.Bool("sso", false, "Use SSO auth flow") ssocli := flagSet.String("ssocli", "", "Path to SSO CLI") @@ -93,14 +96,14 @@ func main() { cmd := os.Args[1] // Tasks that fetch the access token. - fetchTasks := map[string]func(*sgauth.Settings){ + fetchTasks := map[string]func(*sgauth.Settings, string){ "fetch": util.Fetch, "header": util.Header, } // Tasks that verify the existing token. infoTasks := map[string]func(string){ - "info": util.Info, + "info": util.Info, "test": util.Test, } @@ -116,9 +119,9 @@ func main() { settings := &sgauth.Settings{ CredentialsJSON: json, - Audience: flagSet.Args()[len(flagSet.Args()) - 1], + Audience: flagSet.Args()[len(flagSet.Args())-1], } - task(settings) + task(settings, *format) } else if *ssoFlag { // SSO flow util.SSOFetch(flagSet.Args()[0], *ssocli, cmd, @@ -140,10 +143,10 @@ func main() { OAuthFlowHandler: defaultAuthorizeFlowHandler, State: "state", } - task(settings) + task(settings, *format) } } else if task, ok := infoTasks[cmd]; ok { - task(flagSet.Args()[len(flagSet.Args()) - 1]) + task(flagSet.Args()[len(flagSet.Args())-1]) } else if cmd == "reset" { util.Reset() } else { diff --git a/go/oauth2l/util/sso.go b/go/oauth2l/util/sso.go index 57b6807..430a6b1 100644 --- a/go/oauth2l/util/sso.go +++ b/go/oauth2l/util/sso.go @@ -36,5 +36,9 @@ func SSOFetch(email string, cli string, task string, scope string) { if err != nil { fmt.Println(err) } - PrintToken("Bearer", out.String(), task == "header") + if task == "header" { + printHeader("Bearer", out.String()) + } else { + println(out.String()) + } } diff --git a/go/oauth2l/util/tasks.go b/go/oauth2l/util/tasks.go index 9c74127..73084a7 100644 --- a/go/oauth2l/util/tasks.go +++ b/go/oauth2l/util/tasks.go @@ -21,35 +21,34 @@ import ( "errors" "github.com/google/oauth2l/go/sgauth" "context" + "encoding/json" + "log" ) const ( // Base URL to fetch the token info - googleTokenInfoURLPrefix = - "https://www.googleapis.com/oauth2/v3/tokeninfo/?access_token=" + googleTokenInfoURLPrefix = "https://www.googleapis.com/oauth2/v3/tokeninfo/?access_token=" ) -// Prints the token in either plain or header format -func PrintToken(tokenType string, token string, headerFormat bool) { - if headerFormat { - fmt.Printf("Authorization: %s %s\n", tokenType, token) - } else { - fmt.Println(token) - } -} +// Supported output formats +const ( + formatJson = "json" + formatJsonCompact = "json_compact" + formatPretty = "pretty" + formatHeader = "header" + formatBare = "bare" +) // Fetches and prints the token in plain text with the given settings // using Google Authenticator. -func Fetch(settings *sgauth.Settings) { - token := fetchToken(settings) - PrintToken(token.TokenType, token.AccessToken, false) +func Fetch(settings *sgauth.Settings, format string) { + printToken(fetchToken(settings), format, getCredentialType(settings)) } // Fetches and prints the token in header format with the given settings // using Google Authenticator. -func Header(settings *sgauth.Settings) { - token := fetchToken(settings) - PrintToken(token.TokenType, token.AccessToken, true) +func Header(settings *sgauth.Settings, format string) { + Fetch(settings, formatHeader) } // Fetch the information of the given token. @@ -109,3 +108,47 @@ func fetchToken(settings *sgauth.Settings) (*sgauth.Token) { } return token } + +func getCredentialType(settings *sgauth.Settings) (string) { + cred, err := sgauth.FindJSONCredentials(context.Background(), settings) + if err != nil { + return "" + } + return cred.Type +} + +// Prints the token with the specified format +func printToken(token *sgauth.Token, format string, credType string) { + switch format { + case formatBare: + fmt.Println(token.AccessToken) + case formatHeader: + printHeader(token.TokenType, token.AccessToken) + case formatJson: + json, err := json.MarshalIndent(token.Raw, "", " ") + if err != nil { + log.Fatal(err.Error()) + return + } + fmt.Println(string(json)) + case formatJsonCompact: + json, err := json.Marshal(token.Raw) + if err != nil { + log.Fatal(err.Error()) + return + } + fmt.Println(string(json)) + case formatPretty: + fmt.Printf("Fetched credentials of type:\n %s\n"+ + "Access Token:\n %s\n", + credType, token.AccessToken) + default: + log.Fatalf("Invalid choice: '%s' "+ + "(choose from 'bare', 'header', 'json', 'json_compact', 'pretty')", + format) + } +} + +func printHeader(tokenType string, token string) { + fmt.Printf("Authorization: %s %s\n", tokenType, token) +} diff --git a/go/sgauth/credentials/credentials.go b/go/sgauth/credentials/credentials.go index e8caf6f..adc9758 100644 --- a/go/sgauth/credentials/credentials.go +++ b/go/sgauth/credentials/credentials.go @@ -28,4 +28,7 @@ type Credentials struct { // environment and not with a credentials file, e.g. when code is // running on Google Cloud Platform. JSON []byte + + // The type of the credentials. e.g. service account. + Type string } diff --git a/go/sgauth/default.go b/go/sgauth/default.go index 7d360cb..47a2ce6 100644 --- a/go/sgauth/default.go +++ b/go/sgauth/default.go @@ -41,7 +41,7 @@ func DefaultTokenSource(ctx context.Context, scope string) (internal.TokenSource } func OAuthJSONTokenSource(ctx context.Context, settings *Settings) (internal.TokenSource, error) { - creds, err := findJSONCredentials(ctx, settings) + creds, err := FindJSONCredentials(ctx, settings) if err != nil { return nil, err } @@ -50,7 +50,7 @@ func OAuthJSONTokenSource(ctx context.Context, settings *Settings) (internal.Tok } func JWTTokenSource(ctx context.Context, settings *Settings) (internal.TokenSource, error) { - creds, err := findJSONCredentials(ctx, settings) + creds, err := FindJSONCredentials(ctx, settings) if err != nil { return nil, err } @@ -58,7 +58,7 @@ func JWTTokenSource(ctx context.Context, settings *Settings) (internal.TokenSour return ts, err } -func findJSONCredentials(ctx context.Context, settings *Settings) (*credentials.Credentials, error) { +func FindJSONCredentials(ctx context.Context, settings *Settings) (*credentials.Credentials, error) { if settings.CredentialsJSON != "" { return credentialsFromJSON(ctx, []byte(settings.CredentialsJSON), strings.Split(settings.Scope, " "), settings.OAuthFlowHandler, settings.State) @@ -131,6 +131,7 @@ func credentialsFromJSON(ctx context.Context, jsonData []byte, scopes []string, ProjectID: f.ProjectID, TokenSource: ts, JSON: jsonData, + Type: f.CredentialsType(), }, nil }