Skip to content

Commit 8d2c8d8

Browse files
[CLI] --decode flag to decode IDP token to JSON (#18750)
* [CLI] `--decode` flag to decode IDP token to JSON * Marhsal into a map into a proper JSON output
1 parent e5d03e1 commit 8d2c8d8

File tree

1 file changed

+56
-0
lines changed

1 file changed

+56
-0
lines changed

components/gitpod-cli/cmd/idp-token.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ package cmd
66

77
import (
88
"context"
9+
"encoding/base64"
10+
"encoding/json"
911
"fmt"
12+
"strings"
1013
"time"
1114

1215
connect "github.com/bufbuild/connect-go"
@@ -23,6 +26,7 @@ import (
2326

2427
var idpTokenOpts struct {
2528
Audience []string
29+
Decode bool
2630
}
2731

2832
var idpTokenCmd = &cobra.Command{
@@ -35,6 +39,56 @@ var idpTokenCmd = &cobra.Command{
3539
defer cancel()
3640

3741
tkn, err := idpToken(ctx, idpTokenOpts.Audience)
42+
43+
// If the user wants to decode the token, then do so.
44+
if idpTokenOpts.Decode {
45+
// Split the token into its three parts.
46+
parts := strings.Split(tkn, ".")
47+
if len(parts) != 3 {
48+
xerrors.Errorf("JWT token is not valid")
49+
}
50+
51+
// Decode the header.
52+
header, err := base64.RawURLEncoding.DecodeString(parts[0])
53+
if err != nil {
54+
xerrors.Errorf("Failed to decode header: ", err)
55+
}
56+
57+
// Decode the payload.
58+
payload, err := base64.RawURLEncoding.DecodeString(parts[1])
59+
if err != nil {
60+
xerrors.Errorf("Failed to decode payload: ", err)
61+
}
62+
63+
// Unmarshal the header and payload into JSON.
64+
var headerJSON map[string]interface{}
65+
var payloadJSON map[string]interface{}
66+
67+
// This function unmarshals the header and payload of a JWT.
68+
// The header is unmarshalled into a HeaderJSON struct, and the payload is unmarshalled into a PayloadJSON struct.
69+
if err := json.Unmarshal(header, &headerJSON); err != nil {
70+
xerrors.Errorf("Failed to unmarshal header: ", err)
71+
}
72+
73+
if err := json.Unmarshal(payload, &payloadJSON); err != nil {
74+
xerrors.Errorf("Failed to unmarshal payload: ", err)
75+
}
76+
77+
output := map[string]interface{}{
78+
"Header": headerJSON,
79+
"Payload": payloadJSON,
80+
}
81+
82+
// The header and payload are then marshalled into a map and printed to the screen.
83+
outputPretty, err := json.MarshalIndent(output, "", " ")
84+
if err != nil {
85+
xerrors.Errorf("Failed to marshal output: ", err)
86+
}
87+
88+
fmt.Printf("%s\n", outputPretty)
89+
return nil
90+
}
91+
3892
if err != nil {
3993
return err
4094
}
@@ -86,4 +140,6 @@ func init() {
86140

87141
idpTokenCmd.Flags().StringArrayVar(&idpTokenOpts.Audience, "audience", nil, "audience of the ID token")
88142
_ = idpTokenCmd.MarkFlagRequired("audience")
143+
144+
idpTokenCmd.Flags().BoolVar(&idpTokenOpts.Decode, "decode", false, "decode token to JSON")
89145
}

0 commit comments

Comments
 (0)