Skip to content

Commit

Permalink
Adds go module support /v4 (#41)
Browse files Browse the repository at this point in the history
Additionally, added `staticcheck` for basic static code analysis (#44)

Co-authored-by: Christian Banse <oxisto@aybaze.com>
  • Loading branch information
mfridman and oxisto committed Aug 3, 2021
1 parent 4bbdd8a commit 2ebb50f
Show file tree
Hide file tree
Showing 40 changed files with 183 additions and 174 deletions.
17 changes: 12 additions & 5 deletions .github/workflows/build.yml
Expand Up @@ -8,6 +8,18 @@ on:
types: [opened, synchronize, reopened]

jobs:
check:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- uses: reviewdog/action-staticcheck@v1
with:
github_token: ${{ secrets.github_token }}
reporter: github-pr-review
filter_mode: nofilter
fail_on_error: true

build:
runs-on: ubuntu-latest
strategy:
Expand All @@ -17,8 +29,6 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v2
with:
path: src/github.com/golang-jwt/jwt
- name: Setup Go
uses: actions/setup-go@v2
with:
Expand All @@ -28,6 +38,3 @@ jobs:
go vet ./...
go test -v ./...
go build ./...
env:
GO111MODULE: auto
GOPATH: ${{ github.workspace }}
22 changes: 11 additions & 11 deletions MIGRATION_GUIDE.md
@@ -1,22 +1,22 @@
## Migration Guide (v3.2.1)
## Migration Guide (v4.0.0)

Starting from [v3.2.1](https://github.com/golang-jwt/jwt/releases/tag/v3.2.1]), the import path has changed from `github.com/dgrijalva/jwt-go` to `github.com/golang-jwt/jwt`. Future releases will be using the `github.com/golang-jwt/jwt` import path and continue the existing versioning scheme of `v3.x.x+incompatible`. Backwards-compatible patches and fixes will be done on the `v3` release branch, where as new build-breaking features will be developed in a `v4` release, possibly including a SIV-style import path.
Starting from [v4.0.0](https://github.com/golang-jwt/jwt/releases/tag/v4.0.0]), the import path will be:

### go.mod replacement
"github.com/golang-jwt/jwt/v4"

In a first step, the easiest way is to use `go mod edit` to issue a replacement.
The `/v4` version will be backwards compatible with existing `v3.x.y` tags in this repo, as well as
`github.com/dgrijalva/jwt-go`. For most users this should be a drop-in replacement, if you're having
troubles migrating, please open an issue.

You can replace all occurrences of `github.com/dgrijalva/jwt-go` or `github.com/golang-jwt/jwt` with `github.com/golang-jwt/jwt/v4`, either manually or by using tools such as `sed` or `gofmt`.

And then you'd typically run:

```
go mod edit -replace github.com/dgrijalva/jwt-go=github.com/golang-jwt/jwt@v3.2.1+incompatible
go get github.com/golang-jwt/jwt/v4
go mod tidy
```

This will still keep the old import path in your code but replace it with the new package and also introduce a new indirect dependency to `github.com/golang-jwt/jwt`. Try to compile your project; it should still work.

### Cleanup

If your code still consistently builds, you can replace all occurences of `github.com/dgrijalva/jwt-go` with `github.com/golang-jwt/jwt`, either manually or by using tools such as `sed`. Finally, the `replace` directive in the `go.mod` file can be removed.

## Older releases (before v3.2.0)

The original migration guide for older releases can be found at https://github.com/dgrijalva/jwt-go/blob/master/MIGRATION_GUIDE.md.
10 changes: 5 additions & 5 deletions README.md
Expand Up @@ -5,9 +5,11 @@

A [go](http://www.golang.org) (or 'golang' for search engine friendliness) implementation of [JSON Web Tokens](https://datatracker.ietf.org/doc/html/rfc7519).

**IMPORT PATH CHANGE:** Starting from [v3.2.1](https://github.com/golang-jwt/jwt/releases/tag/v3.2.1), the import path has changed from `github.com/dgrijalva/jwt-go` to `github.com/golang-jwt/jwt`. After the original author of the library suggested migrating the maintenance of `jwt-go`, a dedicated team of open source maintainers decided to clone the existing library into this repository. See [dgrijalva/jwt-go#462](https://github.com/dgrijalva/jwt-go/issues/462) for a detailed discussion on this topic.
Starting with [v4.0.0](https://github.com/golang-jwt/jwt/releases/tag/v4.0.0) this project adds Go module support, but maintains backwards compataibility with older `v3.x.y` tags and upstream `github.com/dgrijalva/jwt-go`.
See the `MIGRATION_GUIDE.md` for more information.

> After the original author of the library suggested migrating the maintenance of `jwt-go`, a dedicated team of open source maintainers decided to clone the existing library into this repository. See [dgrijalva/jwt-go#462](https://github.com/dgrijalva/jwt-go/issues/462) for a detailed discussion on this topic.
Future releases will be using the `github.com/golang-jwt/jwt` import path and continue the existing versioning scheme of `v3.x.x+incompatible`. Backwards-compatible patches and fixes will be done on the `v3` release branch, where as new build-breaking features will be developed in a `v4` release, possibly including a SIV-style import path.

**SECURITY NOTICE:** Some older versions of Go have a security issue in the crypto/elliptic. Recommendation is to upgrade to at least 1.15 See issue [dgrijalva/jwt-go#216](https://github.com/dgrijalva/jwt-go/issues/216) for more detail.

Expand Down Expand Up @@ -60,10 +62,8 @@ This library is considered production ready. Feedback and feature requests are

This project uses [Semantic Versioning 2.0.0](http://semver.org). Accepted pull requests will land on `main`. Periodically, versions will be tagged from `main`. You can find all the releases on [the project releases page](https://github.com/golang-jwt/jwt/releases).

While we try to make it obvious when we make breaking changes, there isn't a great mechanism for pushing announcements out to users. You may want to use this alternative package include: `gopkg.in/golang-jwt/jwt.v3`. It will do the right thing WRT semantic versioning.

**BREAKING CHANGES:***
* Version 3.0.0 includes _a lot_ of changes from the 2.x line, including a few that break the API. We've tried to break as few things as possible, so there should just be a few type signature changes. A full list of breaking changes is available in `VERSION_HISTORY.md`. See `MIGRATION_GUIDE.md` for more information on updating your code.
A full list of breaking changes is available in `VERSION_HISTORY.md`. See `MIGRATION_GUIDE.md` for more information on updating your code.

## Usage Tips

Expand Down
4 changes: 4 additions & 0 deletions VERSION_HISTORY.md
@@ -1,5 +1,9 @@
## `jwt-go` Version History

#### 4.0.0

* Introduces support for Go modules. The `v4` version will be backwards compatible with `v3.x.y`.

#### 3.2.2

* Starting from this release, we are adopting the policy to support the most 2 recent versions of Go currently available. By the time of this release, this is Go 1.15 and 1.16 ([#28](https://github.com/golang-jwt/jwt/pull/28)).
Expand Down
17 changes: 8 additions & 9 deletions claims.go
Expand Up @@ -6,13 +6,13 @@ import (
"time"
)

// For a type to be a Claims object, it must just have a Valid method that determines
// Claims must just have a Valid method that determines
// if the token is invalid for any supported reason
type Claims interface {
Valid() error
}

// Structured version of Claims Section, as referenced at
// StandardClaims are a structured version of the Claims Section, as referenced at
// https://tools.ietf.org/html/rfc7519#section-4.1
// See examples for how to use this with your own claim types
type StandardClaims struct {
Expand All @@ -25,8 +25,7 @@ type StandardClaims struct {
Subject string `json:"sub,omitempty"`
}

// Validates time based claims "exp, iat, nbf".
// There is no accounting for clock skew.
// Valid validates time based claims "exp, iat, nbf". There is no accounting for clock skew.
// As well, if any of the above claims are not in the token, it will still
// be considered a valid claim.
func (c StandardClaims) Valid() error {
Expand Down Expand Up @@ -58,31 +57,31 @@ func (c StandardClaims) Valid() error {
return vErr
}

// Compares the aud claim against cmp.
// VerifyAudience compares the aud claim against cmp.
// If required is false, this method will return true if the value matches or is unset
func (c *StandardClaims) VerifyAudience(cmp string, req bool) bool {
return verifyAud([]string{c.Audience}, cmp, req)
}

// Compares the exp claim against cmp.
// VerifyExpiresAt compares the exp claim against cmp.
// If required is false, this method will return true if the value matches or is unset
func (c *StandardClaims) VerifyExpiresAt(cmp int64, req bool) bool {
return verifyExp(c.ExpiresAt, cmp, req)
}

// Compares the iat claim against cmp.
// VerifyIssuedAt compares the iat claim against cmp.
// If required is false, this method will return true if the value matches or is unset
func (c *StandardClaims) VerifyIssuedAt(cmp int64, req bool) bool {
return verifyIat(c.IssuedAt, cmp, req)
}

// Compares the iss claim against cmp.
// VerifyIssuer compares the iss claim against cmp.
// If required is false, this method will return true if the value matches or is unset
func (c *StandardClaims) VerifyIssuer(cmp string, req bool) bool {
return verifyIss(c.Issuer, cmp, req)
}

// Compares the nbf claim against cmp.
// VerifyNotBefore compares the nbf claim against cmp.
// If required is false, this method will return true if the value matches or is unset
func (c *StandardClaims) VerifyNotBefore(cmp int64, req bool) bool {
return verifyNbf(c.NotBefore, cmp, req)
Expand Down
3 changes: 1 addition & 2 deletions cmd/jwt/README.md
Expand Up @@ -16,5 +16,4 @@ To simply display a token, use:

You can install this tool with the following command:

go install github.com/golang-jwt/jwt/cmd/jwt

go install github.com/golang-jwt/jwt/v4/cmd/jwt
23 changes: 0 additions & 23 deletions cmd/jwt/args.go

This file was deleted.

54 changes: 35 additions & 19 deletions cmd/jwt/app.go → cmd/jwt/main.go
Expand Up @@ -16,7 +16,7 @@ import (
"regexp"
"strings"

"github.com/golang-jwt/jwt"
"github.com/golang-jwt/jwt/v4"
)

var (
Expand Down Expand Up @@ -67,14 +67,14 @@ func start() error {
return showToken()
} else {
flag.Usage()
return fmt.Errorf("None of the required flags are present. What do you want me to do?")
return fmt.Errorf("none of the required flags are present. What do you want me to do?")
}
}

// Helper func: Read input from specified file or stdin
func loadData(p string) ([]byte, error) {
if p == "" {
return nil, fmt.Errorf("No path specified")
return nil, fmt.Errorf("no path specified")
}

var rdr io.Reader
Expand Down Expand Up @@ -117,7 +117,7 @@ func verifyToken() error {
// get the token
tokData, err := loadData(*flagVerify)
if err != nil {
return fmt.Errorf("Couldn't read token: %v", err)
return fmt.Errorf("couldn't read token: %w", err)
}

// trim possible whitespace from token
Expand Down Expand Up @@ -150,17 +150,17 @@ func verifyToken() error {

// Print an error if we can't parse for some reason
if err != nil {
return fmt.Errorf("Couldn't parse token: %v", err)
return fmt.Errorf("couldn't parse token: %w", err)
}

// Is token invalid?
if !token.Valid {
return fmt.Errorf("Token is invalid")
return fmt.Errorf("token is invalid")
}

// Print the token details
if err := printJSON(token.Claims); err != nil {
return fmt.Errorf("Failed to output claims: %v", err)
return fmt.Errorf("failed to output claims: %w", err)
}

return nil
Expand All @@ -172,15 +172,15 @@ func signToken() error {
// get the token data from command line arguments
tokData, err := loadData(*flagSign)
if err != nil {
return fmt.Errorf("Couldn't read token: %v", err)
return fmt.Errorf("couldn't read token: %w", err)
} else if *flagDebug {
fmt.Fprintf(os.Stderr, "Token: %v bytes", len(tokData))
}

// parse the JSON of the claims
var claims jwt.MapClaims
if err := json.Unmarshal(tokData, &claims); err != nil {
return fmt.Errorf("Couldn't parse claims JSON: %v", err)
return fmt.Errorf("couldn't parse claims JSON: %w", err)
}

// add command line claims
Expand All @@ -194,13 +194,13 @@ func signToken() error {
var key interface{}
key, err = loadData(*flagKey)
if err != nil {
return fmt.Errorf("Couldn't read key: %v", err)
return fmt.Errorf("couldn't read key: %w", err)
}

// get the signing alg
alg := jwt.GetSigningMethod(*flagAlg)
if alg == nil {
return fmt.Errorf("Couldn't find signing method: %v", *flagAlg)
return fmt.Errorf("couldn't find signing method: %v", *flagAlg)
}

// create a new token
Expand All @@ -215,7 +215,7 @@ func signToken() error {

if isEs() {
if k, ok := key.([]byte); !ok {
return fmt.Errorf("Couldn't convert key data to key")
return fmt.Errorf("couldn't convert key data to key")
} else {
key, err = jwt.ParseECPrivateKeyFromPEM(k)
if err != nil {
Expand All @@ -224,7 +224,7 @@ func signToken() error {
}
} else if isRs() {
if k, ok := key.([]byte); !ok {
return fmt.Errorf("Couldn't convert key data to key")
return fmt.Errorf("couldn't convert key data to key")
} else {
key, err = jwt.ParseRSAPrivateKeyFromPEM(k)
if err != nil {
Expand All @@ -233,7 +233,7 @@ func signToken() error {
}
} else if isEd() {
if k, ok := key.([]byte); !ok {
return fmt.Errorf("Couldn't convert key data to key")
return fmt.Errorf("couldn't convert key data to key")
} else {
key, err = jwt.ParseEdPrivateKeyFromPEM(k)
if err != nil {
Expand All @@ -245,7 +245,7 @@ func signToken() error {
if out, err := token.SignedString(key); err == nil {
fmt.Println(out)
} else {
return fmt.Errorf("Error signing token: %v", err)
return fmt.Errorf("error signing token: %w", err)
}

return nil
Expand All @@ -256,7 +256,7 @@ func showToken() error {
// get the token
tokData, err := loadData(*flagShow)
if err != nil {
return fmt.Errorf("Couldn't read token: %v", err)
return fmt.Errorf("couldn't read token: %w", err)
}

// trim possible whitespace from token
Expand All @@ -267,18 +267,18 @@ func showToken() error {

token, err := jwt.Parse(string(tokData), nil)
if token == nil {
return fmt.Errorf("malformed token: %v", err)
return fmt.Errorf("malformed token: %w", err)
}

// Print the token details
fmt.Println("Header:")
if err := printJSON(token.Header); err != nil {
return fmt.Errorf("Failed to output header: %v", err)
return fmt.Errorf("failed to output header: %w", err)
}

fmt.Println("Claims:")
if err := printJSON(token.Claims); err != nil {
return fmt.Errorf("Failed to output claims: %v", err)
return fmt.Errorf("failed to output claims: %w", err)
}

return nil
Expand All @@ -295,3 +295,19 @@ func isRs() bool {
func isEd() bool {
return strings.HasPrefix(strings.ToUpper(*flagAlg), "Ed")
}

type ArgList map[string]string

func (l ArgList) String() string {
data, _ := json.Marshal(l)
return string(data)
}

func (l ArgList) Set(arg string) error {
parts := strings.SplitN(arg, "=", 2)
if len(parts) != 2 {
return fmt.Errorf("invalid argument '%v'. Must use format 'key=value'. %v", arg, parts)
}
l[parts[0]] = parts[1]
return nil
}

0 comments on commit 2ebb50f

Please sign in to comment.