Skip to content

Commit 2ebb50f

Browse files
mfridmanoxisto
andauthored
Adds go module support /v4 (#41)
Additionally, added `staticcheck` for basic static code analysis (#44) Co-authored-by: Christian Banse <oxisto@aybaze.com>
1 parent 4bbdd8a commit 2ebb50f

40 files changed

+183
-174
lines changed

.github/workflows/build.yml

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,18 @@ on:
88
types: [opened, synchronize, reopened]
99

1010
jobs:
11+
check:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Checkout
15+
uses: actions/checkout@v2
16+
- uses: reviewdog/action-staticcheck@v1
17+
with:
18+
github_token: ${{ secrets.github_token }}
19+
reporter: github-pr-review
20+
filter_mode: nofilter
21+
fail_on_error: true
22+
1123
build:
1224
runs-on: ubuntu-latest
1325
strategy:
@@ -17,8 +29,6 @@ jobs:
1729
steps:
1830
- name: Checkout
1931
uses: actions/checkout@v2
20-
with:
21-
path: src/github.com/golang-jwt/jwt
2232
- name: Setup Go
2333
uses: actions/setup-go@v2
2434
with:
@@ -28,6 +38,3 @@ jobs:
2838
go vet ./...
2939
go test -v ./...
3040
go build ./...
31-
env:
32-
GO111MODULE: auto
33-
GOPATH: ${{ github.workspace }}

MIGRATION_GUIDE.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
1-
## Migration Guide (v3.2.1)
1+
## Migration Guide (v4.0.0)
22

3-
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.
3+
Starting from [v4.0.0](https://github.com/golang-jwt/jwt/releases/tag/v4.0.0]), the import path will be:
44

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

7-
In a first step, the easiest way is to use `go mod edit` to issue a replacement.
7+
The `/v4` version will be backwards compatible with existing `v3.x.y` tags in this repo, as well as
8+
`github.com/dgrijalva/jwt-go`. For most users this should be a drop-in replacement, if you're having
9+
troubles migrating, please open an issue.
10+
11+
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`.
12+
13+
And then you'd typically run:
814

915
```
10-
go mod edit -replace github.com/dgrijalva/jwt-go=github.com/golang-jwt/jwt@v3.2.1+incompatible
16+
go get github.com/golang-jwt/jwt/v4
1117
go mod tidy
1218
```
1319

14-
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.
15-
16-
### Cleanup
17-
18-
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.
19-
2020
## Older releases (before v3.2.0)
2121

2222
The original migration guide for older releases can be found at https://github.com/dgrijalva/jwt-go/blob/master/MIGRATION_GUIDE.md.

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55

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

8-
**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.
8+
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`.
9+
See the `MIGRATION_GUIDE.md` for more information.
10+
11+
> 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.
912
10-
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.
1113

1214
**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.
1315

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

6163
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).
6264

63-
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.
64-
6565
**BREAKING CHANGES:***
66-
* 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.
66+
A full list of breaking changes is available in `VERSION_HISTORY.md`. See `MIGRATION_GUIDE.md` for more information on updating your code.
6767

6868
## Usage Tips
6969

VERSION_HISTORY.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
## `jwt-go` Version History
22

3+
#### 4.0.0
4+
5+
* Introduces support for Go modules. The `v4` version will be backwards compatible with `v3.x.y`.
6+
37
#### 3.2.2
48

59
* 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)).

claims.go

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ import (
66
"time"
77
)
88

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

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

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

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

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

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

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

85-
// Compares the nbf claim against cmp.
84+
// VerifyNotBefore compares the nbf claim against cmp.
8685
// If required is false, this method will return true if the value matches or is unset
8786
func (c *StandardClaims) VerifyNotBefore(cmp int64, req bool) bool {
8887
return verifyNbf(c.NotBefore, cmp, req)

cmd/jwt/README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,4 @@ To simply display a token, use:
1616

1717
You can install this tool with the following command:
1818

19-
go install github.com/golang-jwt/jwt/cmd/jwt
20-
19+
go install github.com/golang-jwt/jwt/v4/cmd/jwt

cmd/jwt/args.go

Lines changed: 0 additions & 23 deletions
This file was deleted.

cmd/jwt/app.go renamed to cmd/jwt/main.go

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616
"regexp"
1717
"strings"
1818

19-
"github.com/golang-jwt/jwt"
19+
"github.com/golang-jwt/jwt/v4"
2020
)
2121

2222
var (
@@ -67,14 +67,14 @@ func start() error {
6767
return showToken()
6868
} else {
6969
flag.Usage()
70-
return fmt.Errorf("None of the required flags are present. What do you want me to do?")
70+
return fmt.Errorf("none of the required flags are present. What do you want me to do?")
7171
}
7272
}
7373

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

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

123123
// trim possible whitespace from token
@@ -150,17 +150,17 @@ func verifyToken() error {
150150

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

156156
// Is token invalid?
157157
if !token.Valid {
158-
return fmt.Errorf("Token is invalid")
158+
return fmt.Errorf("token is invalid")
159159
}
160160

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

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

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

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

200200
// get the signing alg
201201
alg := jwt.GetSigningMethod(*flagAlg)
202202
if alg == nil {
203-
return fmt.Errorf("Couldn't find signing method: %v", *flagAlg)
203+
return fmt.Errorf("couldn't find signing method: %v", *flagAlg)
204204
}
205205

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

216216
if isEs() {
217217
if k, ok := key.([]byte); !ok {
218-
return fmt.Errorf("Couldn't convert key data to key")
218+
return fmt.Errorf("couldn't convert key data to key")
219219
} else {
220220
key, err = jwt.ParseECPrivateKeyFromPEM(k)
221221
if err != nil {
@@ -224,7 +224,7 @@ func signToken() error {
224224
}
225225
} else if isRs() {
226226
if k, ok := key.([]byte); !ok {
227-
return fmt.Errorf("Couldn't convert key data to key")
227+
return fmt.Errorf("couldn't convert key data to key")
228228
} else {
229229
key, err = jwt.ParseRSAPrivateKeyFromPEM(k)
230230
if err != nil {
@@ -233,7 +233,7 @@ func signToken() error {
233233
}
234234
} else if isEd() {
235235
if k, ok := key.([]byte); !ok {
236-
return fmt.Errorf("Couldn't convert key data to key")
236+
return fmt.Errorf("couldn't convert key data to key")
237237
} else {
238238
key, err = jwt.ParseEdPrivateKeyFromPEM(k)
239239
if err != nil {
@@ -245,7 +245,7 @@ func signToken() error {
245245
if out, err := token.SignedString(key); err == nil {
246246
fmt.Println(out)
247247
} else {
248-
return fmt.Errorf("Error signing token: %v", err)
248+
return fmt.Errorf("error signing token: %w", err)
249249
}
250250

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

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

268268
token, err := jwt.Parse(string(tokData), nil)
269269
if token == nil {
270-
return fmt.Errorf("malformed token: %v", err)
270+
return fmt.Errorf("malformed token: %w", err)
271271
}
272272

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

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

284284
return nil
@@ -295,3 +295,19 @@ func isRs() bool {
295295
func isEd() bool {
296296
return strings.HasPrefix(strings.ToUpper(*flagAlg), "Ed")
297297
}
298+
299+
type ArgList map[string]string
300+
301+
func (l ArgList) String() string {
302+
data, _ := json.Marshal(l)
303+
return string(data)
304+
}
305+
306+
func (l ArgList) Set(arg string) error {
307+
parts := strings.SplitN(arg, "=", 2)
308+
if len(parts) != 2 {
309+
return fmt.Errorf("invalid argument '%v'. Must use format 'key=value'. %v", arg, parts)
310+
}
311+
l[parts[0]] = parts[1]
312+
return nil
313+
}

0 commit comments

Comments
 (0)