Skip to content

Commit

Permalink
Finish functional implementation of jwt signature verification. Closes
Browse files Browse the repository at this point in the history
  • Loading branch information
chclaus committed May 18, 2018
1 parent f2c232b commit ab81a63
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 9 deletions.
62 changes: 54 additions & 8 deletions cmd/jwt/jwt.go
Expand Up @@ -21,20 +21,23 @@
package jwt

import (
"bytes"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"github.com/chclaus/dt/cmd"
"github.com/chclaus/dt/config"
"github.com/chclaus/dt/utils"
"github.com/dgrijalva/jwt-go"
"github.com/fatih/color"
"github.com/hokaccha/go-prettyjson"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"io/ioutil"
"log"
"os"
"strings"
"github.com/spf13/viper"
"github.com/dgrijalva/jwt-go"
"github.com/fatih/color"
"github.com/chclaus/dt/config"
)

// jwtCmd represents the jwt command
Expand All @@ -50,20 +53,27 @@ var jwtCmd = &cobra.Command{
},
Long: "Allows decoding of a jwt.",
Run: func(cmd *cobra.Command, args []string) {
parts := strings.Split(args[0], ".")
jwtString := args[0]
parts := strings.Split(jwtString, ".")
if len(parts) != 3 {
log.Fatal("Invalid JWT. It must has a JOSE Header, JWS Payload and JWS Signature")
}

printJWT(parts)

if config.Cfg.JWT.Secret != "" {
_, err := jwt.Parse(args[0], func(token *jwt.Token) (interface{}, error) {
return []byte(config.Cfg.JWT.Secret), nil
secret, err := determineSecret()
if err != nil {
log.Fatal(err)
}

if secret != nil {
_, err := jwt.Parse(jwtString, func(token *jwt.Token) (interface{}, error) {
return []byte(secret), nil
})
if err != nil {
red := color.New(color.FgRed)
red.Printf("\nOh no! %s.\n", err)
fmt.Printf("Your chosen secret is: '%s'\n", secret)
} else {
green := color.New(color.FgGreen)
green.Printf("\ntoken signature is valid.\n")
Expand All @@ -75,6 +85,38 @@ var jwtCmd = &cobra.Command{
dt jwt eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJmb28iLCJzdWIiOiJiYXIifQ.UxyRHFY_BpuDQ1Qp9MVvbn5uAlaoWCUKUIeq1qQIcCw -s foobar`,
}

func determineSecret() ([]byte, error) {
jwtCfg := config.Cfg.JWT

if jwtCfg.Secret != "" {
if jwtCfg.Base64Secret {
return []byte(utils.DecodeBase64(base64.StdEncoding, jwtCfg.Secret)), nil
}

return []byte(jwtCfg.Secret), nil
}

if jwtCfg.SecretFile != "" {
if _, err := os.Stat(jwtCfg.SecretFile); err != nil {
return nil, fmt.Errorf("secret file doesn't exist: %s", err)
}

b, err := ioutil.ReadFile(jwtCfg.SecretFile)
if err != nil {
return nil, fmt.Errorf("error reading secret file: %s", err)
}

b = bytes.TrimSpace(b)
if jwtCfg.Base64Secret {
return []byte(utils.DecodeBase64(base64.StdEncoding, string(b))), nil
}

return b, nil
}

return nil, nil
}

func printJWT(parts []string) {
fmt.Println("JOSE Header:")
fmt.Println(prettifyPart(parts[0]))
Expand All @@ -96,5 +138,9 @@ func init() {
cmd.RootCmd.AddCommand(jwtCmd)

jwtCmd.Flags().StringP("secret", "s", "", "the secret to validate the token signature")
jwtCmd.Flags().StringP("secretFile", "f", "", "a file of the secret to validate the token signature")
jwtCmd.Flags().BoolP("base64Secret", "b", false, "set to true if the secret is base64 encoded")
viper.BindPFlag("jwt.secret", jwtCmd.Flags().Lookup("secret"))
viper.BindPFlag("jwt.secretFile", jwtCmd.Flags().Lookup("secretFile"))
viper.BindPFlag("jwt.base64Secret", jwtCmd.Flags().Lookup("base64Secret"))
}
4 changes: 3 additions & 1 deletion config/config.go
Expand Up @@ -49,7 +49,9 @@ type HashConfig struct {

// JWTConfig allows configuration settings of the jwt cmd
type JWTConfig struct {
Secret string
Secret string
SecretFile string
Base64Secret bool
}

// Cfg the root object of the configuration
Expand Down

0 comments on commit ab81a63

Please sign in to comment.