diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b7d385f..a89f3f3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,10 +7,10 @@ jobs: runs-on: ubuntu-latest steps: - - name: Set up Go 1.13 + - name: Set up Go 1.14 uses: actions/setup-go@v1 with: - go-version: 1.13 + go-version: 1.14 id: go - name: Check out code @@ -25,7 +25,7 @@ jobs: run: go build . - name: Test - run: go test -v . + run: go test -v ./... - name: Generate Coverage run: go test -coverprofile=coverage.txt diff --git a/README.md b/README.md index f814c4d..e47cde4 100644 --- a/README.md +++ b/README.md @@ -18,32 +18,61 @@ JSON Web Tokens for Go Go version 1.13 ``` -go get github.com/cristalhq/jwt +go get github.com/cristalhq/jwt/v3 ``` ## Example ```go +// 1. create a signer & a verifier key := []byte(`secret`) -signer, errSigner := jwt.NewHS256(key) -builder := jwt.NewBuilder(signer) +signer, err := jwt.NewSignerHS(jwt.HS256, key) +checkErr(err) +verifier, err := jwt.NewVerifierHS(jwt.HS256, key) +checkErr(err) +// 2. create q standard claims +// (you can create your own, see: Example_BuildUserClaims) claims := &jwt.StandardClaims{ Audience: []string{"admin"}, ID: "random-unique-string", } -token, errBuild := builder.Build(claims) -raw := token.Raw() // JWT signed token +// 3. create a builder +builder := jwt.NewBuilder(signer) + +// 4. and build a token +token, err := builder.Build(claims) + +// 5. here is your token :) +var _ []byte = token.Raw() // or just token.String() for string + +// 6. parse a token (by example received from a request) +tokenStr := token.String() +newToken, errParse := jwt.ParseString(tokenStr) +checkErr(errParse) + +// 7. and verify it's signature +errVerify := verifier.Verify(newToken.Payload(), newToken.Signature()) +checkErr(errVerify) + +// 8. also you can parse and verify in 1 operation +newToken, err = jwt.ParseAndVerifyString(tokenStr, verifier) +checkErr(err) + +// 9. get standard claims +var newClaims jwt.StandardClaims +errClaims := json.Unmarshal(newToken.RawClaims(), &newClaims) +checkErr(errClaims) -errVerify := signer.Verify(token.Payload(), token.Signature()) +// 10. see docs for more methods ``` -Also see examples: [build](https://github.com/cristalhq/jwt/blob/master/example_build_test.go), [parse](https://github.com/cristalhq/jwt/blob/master/example_parse_test.go). +Also see examples: [this above](https://github.com/cristalhq/jwt/blob/master/example_test.go), [build](https://github.com/cristalhq/jwt/blob/master/example_build_test.go), [parse](https://github.com/cristalhq/jwt/blob/master/example_parse_test.go). ## Documentation -See [these docs](https://godoc.org/github.com/cristalhq/jwt). +See [these docs](https://godoc.org/github.com/cristalhq/jwt/v3). ## License @@ -52,7 +81,7 @@ See [these docs](https://godoc.org/github.com/cristalhq/jwt). [build-img]: https://github.com/cristalhq/jwt/workflows/build/badge.svg [build-url]: https://github.com/cristalhq/jwt/actions [doc-img]: https://godoc.org/github.com/cristalhq/jwt?status.svg -[doc-url]: https://godoc.org/github.com/cristalhq/jwt +[doc-url]: https://pkg.go.dev/github.com/cristalhq/jwt/v3 [reportcard-img]: https://goreportcard.com/badge/cristalhq/jwt [reportcard-url]: https://goreportcard.com/report/cristalhq/jwt [coverage-img]: https://codecov.io/gh/cristalhq/jwt/branch/master/graph/badge.svg diff --git a/example_build_test.go b/example_build_test.go index e2900de..60ae3ff 100644 --- a/example_build_test.go +++ b/example_build_test.go @@ -1,10 +1,9 @@ package jwt_test import ( - "encoding/json" "fmt" - "github.com/cristalhq/jwt/v2" + "github.com/cristalhq/jwt/v3" ) func Example_BuildSimple() { @@ -16,10 +15,8 @@ func Example_BuildSimple() { Audience: []string{"admin"}, ID: "random-unique-string", } - token, errBuild := builder.Build(claims) - if errBuild != nil { - panic(errBuild) - } + token, err := builder.Build(claims) + checkErr(err) fmt.Printf("Algorithm %v\n", token.Header().Algorithm) fmt.Printf("Type %v\n", token.Header().Type) @@ -37,15 +34,10 @@ func Example_BuildSimple() { type userClaims struct { jwt.StandardClaims - IsAdministrator bool `json:"is_admin"` Email string `json:"email"` } -func (u *userClaims) MarshalBinary() ([]byte, error) { - return json.Marshal(u) -} - func Example_BuildUserClaims() { key := []byte(`secret`) signer, _ := jwt.NewSignerHS(jwt.HS256, key) @@ -59,10 +51,8 @@ func Example_BuildUserClaims() { IsAdministrator: true, Email: "foo@bar.baz", } - token, errBuild := builder.Build(claims) - if errBuild != nil { - panic(errBuild) - } + token, err := builder.Build(claims) + checkErr(err) fmt.Printf("Claims %v\n", string(token.RawClaims())) fmt.Printf("Payload %v\n", string(token.Payload())) @@ -76,10 +66,6 @@ func Example_BuildUserClaims() { type dummyClaims map[string]interface{} -func (d *dummyClaims) MarshalBinary() ([]byte, error) { - return json.Marshal(d) -} - func Example_DummyClaims() { key := []byte(`secret`) signer, _ := jwt.NewSignerHS(jwt.HS256, key) @@ -89,10 +75,8 @@ func Example_DummyClaims() { "aUdIeNcE": "@everyone", "well": "well-well-well", }) - token, errBuild := builder.Build(&claims) - if errBuild != nil { - panic(errBuild) - } + token, err := builder.Build(&claims) + checkErr(err) fmt.Printf("Claims %v\n", string(token.RawClaims())) fmt.Printf("Payload %v\n", string(token.Payload())) diff --git a/example_parse_test.go b/example_parse_test.go index de1c3f7..a819593 100644 --- a/example_parse_test.go +++ b/example_parse_test.go @@ -3,16 +3,14 @@ package jwt_test import ( "fmt" - "github.com/cristalhq/jwt/v2" + "github.com/cristalhq/jwt/v3" ) func Example_Parse() { t := `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJhZG1pbiIsImp0aSI6InJhbmRvbS11bmlxdWUtc3RyaW5nIn0.dv9-XpY9P8ypm1uWQwB6eKvq3jeyodLA7brhjsf4JVs` - token, errParse := jwt.Parse([]byte(t)) - if errParse != nil { - panic(errParse) - } + token, err := jwt.Parse([]byte(t)) + checkErr(err) fmt.Printf("Algorithm %v\n", token.Header().Algorithm) fmt.Printf("Type %v\n", token.Header().Type) @@ -34,10 +32,8 @@ func Example_ParseAndVerify() { t := `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJhZG1pbiIsImp0aSI6InJhbmRvbS11bmlxdWUtc3RyaW5nIn0.dv9-XpY9P8ypm1uWQwB6eKvq3jeyodLA7brhjsf4JVs` - token, errParse := jwt.ParseAndVerify([]byte(t), verifier) - if errParse != nil { - panic(errParse) - } + token, err := jwt.ParseAndVerify([]byte(t), verifier) + checkErr(err) fmt.Printf("Algorithm %v\n", token.Header().Algorithm) fmt.Printf("Type %v\n", token.Header().Type) diff --git a/example_test.go b/example_test.go new file mode 100644 index 0000000..5a09e33 --- /dev/null +++ b/example_test.go @@ -0,0 +1,72 @@ +package jwt_test + +import ( + "encoding/json" + "fmt" + + "github.com/cristalhq/jwt/v3" +) + +func Example_JWT() { + // 1. create a signer & a verifier + key := []byte(`secret`) + signer, err := jwt.NewSignerHS(jwt.HS256, key) + checkErr(err) + verifier, err := jwt.NewVerifierHS(jwt.HS256, key) + checkErr(err) + + // 2. create q standard claims + // (you can create your own, see: Example_BuildUserClaims) + claims := &jwt.StandardClaims{ + Audience: []string{"admin"}, + ID: "random-unique-string", + } + + // 3. create a builder + builder := jwt.NewBuilder(signer) + + // 4. and build a token + token, err := builder.Build(claims) + + // 5. here is your token :) + var _ []byte = token.Raw() // or just token.String() for string + + // 6. parse a token (by example received from a request) + tokenStr := token.String() + newToken, errParse := jwt.ParseString(tokenStr) + checkErr(errParse) + + // 7. and verify it's signature + errVerify := verifier.Verify(newToken.Payload(), newToken.Signature()) + checkErr(errVerify) + + // 8. also you can parse and verify in 1 operation + newToken, err = jwt.ParseAndVerifyString(tokenStr, verifier) + checkErr(err) + + // 9. get standard claims + var newClaims jwt.StandardClaims + errClaims := json.Unmarshal(newToken.RawClaims(), &newClaims) + checkErr(errClaims) + + // 10. see docs for more methods + + fmt.Printf("Algorithm %v\n", newToken.Header().Algorithm) + fmt.Printf("Type %v\n", newToken.Header().Type) + fmt.Printf("Claims %v\n", string(newToken.RawClaims())) + fmt.Printf("Payload %v\n", string(newToken.Payload())) + fmt.Printf("Token %v\n", string(newToken.Raw())) + + // Output: + // Algorithm HS256 + // Type JWT + // Claims {"jti":"random-unique-string","aud":"admin"} + // Payload eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJyYW5kb20tdW5pcXVlLXN0cmluZyIsImF1ZCI6ImFkbWluIn0 + // Token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJyYW5kb20tdW5pcXVlLXN0cmluZyIsImF1ZCI6ImFkbWluIn0.uNaqGEggmy02lZq8FM7KoUKXhOy-zrSF7inYuzIET9o +} + +func checkErr(err error) { + if err != nil { + panic(err) + } +} diff --git a/go.mod b/go.mod index 3741be3..da3445d 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ -module github.com/cristalhq/jwt/v2 +module github.com/cristalhq/jwt/v3 go 1.13 diff --git a/jwt_bench_test.go b/jwt_bench_test.go index b1bb361..6c1a58a 100644 --- a/jwt_bench_test.go +++ b/jwt_bench_test.go @@ -10,7 +10,7 @@ import ( "testing" "time" - "github.com/cristalhq/jwt/v2" + "github.com/cristalhq/jwt/v3" ) func BenchmarkAlgEDSA(b *testing.B) { diff --git a/jwt_test.go b/jwt_test.go index 9248b41..3a49f05 100644 --- a/jwt_test.go +++ b/jwt_test.go @@ -25,10 +25,6 @@ type customClaims struct { TestField string `json:"test_field"` } -func (cs *customClaims) MarshalBinary() (data []byte, err error) { - return json.Marshal(cs) -} - func TestMarshalHeader(t *testing.T) { f := func(h *Header, want string) { t.Helper()