mirror of https://github.com/golang-jwt/jwt.git
cmd: add handling of HS keys
Signed-off-by: Paul Greenberg <greenpau@outlook.com>
This commit is contained in:
parent
d0c0939ff8
commit
c6a6a5f45b
|
@ -1,19 +1,97 @@
|
||||||
`jwt` command-line tool
|
# `jwt` command-line tool
|
||||||
=======================
|
|
||||||
|
|
||||||
This is a simple tool to sign, verify and show JSON Web Tokens from
|
This is a simple tool to sign, verify and show JSON Web Tokens from
|
||||||
the command line.
|
the command line.
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
The following will create and sign a token, then verify it and output the original claims:
|
The following will create and sign a token, then verify it and output the original claims:
|
||||||
|
|
||||||
|
```bash
|
||||||
echo {\"foo\":\"bar\"} | ./jwt -key ../../test/sample_key -alg RS256 -sign - | ./jwt -key ../../test/sample_key.pub -alg RS256 -verify -
|
echo {\"foo\":\"bar\"} | ./jwt -key ../../test/sample_key -alg RS256 -sign - | ./jwt -key ../../test/sample_key.pub -alg RS256 -verify -
|
||||||
|
```
|
||||||
|
|
||||||
Key files should be in PEM format. Other formats are not supported by this tool.
|
Key files should be in PEM format. Other formats are not supported by this tool.
|
||||||
|
|
||||||
To simply display a token, use:
|
To simply display a token, use:
|
||||||
|
|
||||||
|
```bash
|
||||||
echo $JWT | ./jwt -show -
|
echo $JWT | ./jwt -show -
|
||||||
|
```
|
||||||
|
|
||||||
You can install this tool with the following command:
|
You can install this tool with the following command:
|
||||||
|
|
||||||
|
```bash
|
||||||
go install github.com/golang-jwt/jwt/v4/cmd/jwt
|
go install github.com/golang-jwt/jwt/v4/cmd/jwt
|
||||||
|
```
|
||||||
|
|
||||||
|
## Sign/Verify with Shared Secret
|
||||||
|
|
||||||
|
First, create a JSON document with token payload, e.g. `~/experimental/jwt/data`.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"email": "jsmith@foo.bar",
|
||||||
|
"aud": "foo.bar",
|
||||||
|
"exp": 2559489932,
|
||||||
|
"iat": 1612805132,
|
||||||
|
"iss": "foo.bar",
|
||||||
|
"sub": "jsmith"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, create a file with shared secret key, e.g. `~/experimental/jwt/token.key`.
|
||||||
|
|
||||||
|
```
|
||||||
|
foobarbaz
|
||||||
|
```
|
||||||
|
|
||||||
|
Next, sign the token:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./jwt -key ~/experimental/jwt/token.key -alg HS512 -sign ~/experimental/jwt/data > ~/experimental/jwt/token.jwt
|
||||||
|
```
|
||||||
|
|
||||||
|
After that, review the token:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./jwt -show ~/experimental/jwt/token.jwt
|
||||||
|
```
|
||||||
|
|
||||||
|
The expected output follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
Header:
|
||||||
|
{
|
||||||
|
"alg": "HS512",
|
||||||
|
"typ": "JWT"
|
||||||
|
}
|
||||||
|
Claims:
|
||||||
|
{
|
||||||
|
"aud": "foo.bar",
|
||||||
|
"email": "jsmith@foo.bar",
|
||||||
|
"exp": 2559489932,
|
||||||
|
"iat": 1612805132,
|
||||||
|
"iss": "foo.bar",
|
||||||
|
"sub": "jsmith"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Subsequently, validate the token:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./jwt -key ~/experimental/jwt/token.key -alg HS512 -verify ~/experimental/jwt/token.jwt
|
||||||
|
```
|
||||||
|
|
||||||
|
The expected output follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"aud": "foo.bar",
|
||||||
|
"email": "jsmith@foo.bar",
|
||||||
|
"exp": 2559489932,
|
||||||
|
"iat": 1612805132,
|
||||||
|
"iss": "foo.bar",
|
||||||
|
"sub": "jsmith"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -16,6 +17,7 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt/v4"
|
"github.com/golang-jwt/jwt/v4"
|
||||||
)
|
)
|
||||||
|
@ -142,6 +144,8 @@ func verifyToken() error {
|
||||||
return jwt.ParseRSAPublicKeyFromPEM(data)
|
return jwt.ParseRSAPublicKeyFromPEM(data)
|
||||||
} else if isEd() {
|
} else if isEd() {
|
||||||
return jwt.ParseEdPublicKeyFromPEM(data)
|
return jwt.ParseEdPublicKeyFromPEM(data)
|
||||||
|
} else if isHs() {
|
||||||
|
return parseHSKey(data)
|
||||||
}
|
}
|
||||||
return data, nil
|
return data, nil
|
||||||
})
|
})
|
||||||
|
@ -196,9 +200,19 @@ func signToken() error {
|
||||||
|
|
||||||
// get the key
|
// get the key
|
||||||
var key interface{}
|
var key interface{}
|
||||||
if isNone() {
|
switch {
|
||||||
|
case isNone():
|
||||||
key = jwt.UnsafeAllowNoneSignatureType
|
key = jwt.UnsafeAllowNoneSignatureType
|
||||||
} else {
|
case isHs():
|
||||||
|
kb, err := loadData(*flagKey)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("couldn't read key: %w", err)
|
||||||
|
}
|
||||||
|
key, err = parseHSKey(kb)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
default:
|
||||||
key, err = loadData(*flagKey)
|
key, err = loadData(*flagKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("couldn't read key: %w", err)
|
return fmt.Errorf("couldn't read key: %w", err)
|
||||||
|
@ -292,6 +306,10 @@ func showToken() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isHs() bool {
|
||||||
|
return strings.HasPrefix(*flagAlg, "HS")
|
||||||
|
}
|
||||||
|
|
||||||
func isEs() bool {
|
func isEs() bool {
|
||||||
return strings.HasPrefix(*flagAlg, "ES")
|
return strings.HasPrefix(*flagAlg, "ES")
|
||||||
}
|
}
|
||||||
|
@ -342,3 +360,17 @@ func (l ArgList) Set(arg string) error {
|
||||||
l[parts[0]] = parts[1]
|
l[parts[0]] = parts[1]
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseHSKey(b []byte) ([]byte, error) {
|
||||||
|
if len(b) == 0 {
|
||||||
|
return nil, fmt.Errorf("shared key is empty")
|
||||||
|
}
|
||||||
|
f := func(c rune) bool {
|
||||||
|
return unicode.IsSpace(c)
|
||||||
|
}
|
||||||
|
i := bytes.IndexFunc(b, f)
|
||||||
|
if i < 0 {
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
return b[:i], nil
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue