forked from mirror/jwt
Adds go module support /v4 (#41)
Additionally, added `staticcheck` for basic static code analysis (#44) Co-authored-by: Christian Banse <oxisto@aybaze.com>
This commit is contained in:
parent
4bbdd8ac62
commit
2ebb50f957
|
@ -8,6 +8,18 @@ on:
|
||||||
types: [opened, synchronize, reopened]
|
types: [opened, synchronize, reopened]
|
||||||
|
|
||||||
jobs:
|
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:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
|
@ -17,8 +29,6 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
with:
|
|
||||||
path: src/github.com/golang-jwt/jwt
|
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
|
@ -28,6 +38,3 @@ jobs:
|
||||||
go vet ./...
|
go vet ./...
|
||||||
go test -v ./...
|
go test -v ./...
|
||||||
go build ./...
|
go build ./...
|
||||||
env:
|
|
||||||
GO111MODULE: auto
|
|
||||||
GOPATH: ${{ github.workspace }}
|
|
||||||
|
|
|
@ -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
|
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)
|
## 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.
|
The original migration guide for older releases can be found at https://github.com/dgrijalva/jwt-go/blob/master/MIGRATION_GUIDE.md.
|
10
README.md
10
README.md
|
@ -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).
|
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.
|
**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.
|
||||||
|
|
||||||
|
@ -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).
|
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:***
|
**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
|
## Usage Tips
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
## `jwt-go` Version History
|
## `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
|
#### 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)).
|
* 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)).
|
||||||
|
|
17
claims.go
17
claims.go
|
@ -6,13 +6,13 @@ import (
|
||||||
"time"
|
"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
|
// if the token is invalid for any supported reason
|
||||||
type Claims interface {
|
type Claims interface {
|
||||||
Valid() error
|
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
|
// https://tools.ietf.org/html/rfc7519#section-4.1
|
||||||
// See examples for how to use this with your own claim types
|
// See examples for how to use this with your own claim types
|
||||||
type StandardClaims struct {
|
type StandardClaims struct {
|
||||||
|
@ -25,8 +25,7 @@ type StandardClaims struct {
|
||||||
Subject string `json:"sub,omitempty"`
|
Subject string `json:"sub,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validates time based claims "exp, iat, nbf".
|
// Valid validates time based claims "exp, iat, nbf". There is no accounting for clock skew.
|
||||||
// There is no accounting for clock skew.
|
|
||||||
// As well, if any of the above claims are not in the token, it will still
|
// As well, if any of the above claims are not in the token, it will still
|
||||||
// be considered a valid claim.
|
// be considered a valid claim.
|
||||||
func (c StandardClaims) Valid() error {
|
func (c StandardClaims) Valid() error {
|
||||||
|
@ -58,31 +57,31 @@ func (c StandardClaims) Valid() error {
|
||||||
return vErr
|
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
|
// 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 {
|
func (c *StandardClaims) VerifyAudience(cmp string, req bool) bool {
|
||||||
return verifyAud([]string{c.Audience}, cmp, req)
|
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
|
// 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 {
|
func (c *StandardClaims) VerifyExpiresAt(cmp int64, req bool) bool {
|
||||||
return verifyExp(c.ExpiresAt, cmp, req)
|
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
|
// 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 {
|
func (c *StandardClaims) VerifyIssuedAt(cmp int64, req bool) bool {
|
||||||
return verifyIat(c.IssuedAt, cmp, req)
|
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
|
// 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 {
|
func (c *StandardClaims) VerifyIssuer(cmp string, req bool) bool {
|
||||||
return verifyIss(c.Issuer, cmp, req)
|
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
|
// 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 {
|
func (c *StandardClaims) VerifyNotBefore(cmp int64, req bool) bool {
|
||||||
return verifyNbf(c.NotBefore, cmp, req)
|
return verifyNbf(c.NotBefore, cmp, req)
|
||||||
|
|
|
@ -16,5 +16,4 @@ To simply display a token, use:
|
||||||
|
|
||||||
You can install this tool with the following command:
|
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
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
|
@ -16,7 +16,7 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt"
|
"github.com/golang-jwt/jwt/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -67,14 +67,14 @@ func start() error {
|
||||||
return showToken()
|
return showToken()
|
||||||
} else {
|
} else {
|
||||||
flag.Usage()
|
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
|
// Helper func: Read input from specified file or stdin
|
||||||
func loadData(p string) ([]byte, error) {
|
func loadData(p string) ([]byte, error) {
|
||||||
if p == "" {
|
if p == "" {
|
||||||
return nil, fmt.Errorf("No path specified")
|
return nil, fmt.Errorf("no path specified")
|
||||||
}
|
}
|
||||||
|
|
||||||
var rdr io.Reader
|
var rdr io.Reader
|
||||||
|
@ -117,7 +117,7 @@ func verifyToken() error {
|
||||||
// get the token
|
// get the token
|
||||||
tokData, err := loadData(*flagVerify)
|
tokData, err := loadData(*flagVerify)
|
||||||
if err != nil {
|
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
|
// trim possible whitespace from token
|
||||||
|
@ -150,17 +150,17 @@ func verifyToken() error {
|
||||||
|
|
||||||
// Print an error if we can't parse for some reason
|
// Print an error if we can't parse for some reason
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Couldn't parse token: %v", err)
|
return fmt.Errorf("couldn't parse token: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is token invalid?
|
// Is token invalid?
|
||||||
if !token.Valid {
|
if !token.Valid {
|
||||||
return fmt.Errorf("Token is invalid")
|
return fmt.Errorf("token is invalid")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print the token details
|
// Print the token details
|
||||||
if err := printJSON(token.Claims); err != nil {
|
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
|
return nil
|
||||||
|
@ -172,7 +172,7 @@ func signToken() error {
|
||||||
// get the token data from command line arguments
|
// get the token data from command line arguments
|
||||||
tokData, err := loadData(*flagSign)
|
tokData, err := loadData(*flagSign)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Couldn't read token: %v", err)
|
return fmt.Errorf("couldn't read token: %w", err)
|
||||||
} else if *flagDebug {
|
} else if *flagDebug {
|
||||||
fmt.Fprintf(os.Stderr, "Token: %v bytes", len(tokData))
|
fmt.Fprintf(os.Stderr, "Token: %v bytes", len(tokData))
|
||||||
}
|
}
|
||||||
|
@ -180,7 +180,7 @@ func signToken() error {
|
||||||
// parse the JSON of the claims
|
// parse the JSON of the claims
|
||||||
var claims jwt.MapClaims
|
var claims jwt.MapClaims
|
||||||
if err := json.Unmarshal(tokData, &claims); err != nil {
|
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
|
// add command line claims
|
||||||
|
@ -194,13 +194,13 @@ func signToken() error {
|
||||||
var key interface{}
|
var key interface{}
|
||||||
key, err = loadData(*flagKey)
|
key, err = loadData(*flagKey)
|
||||||
if err != nil {
|
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
|
// get the signing alg
|
||||||
alg := jwt.GetSigningMethod(*flagAlg)
|
alg := jwt.GetSigningMethod(*flagAlg)
|
||||||
if alg == nil {
|
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
|
// create a new token
|
||||||
|
@ -215,7 +215,7 @@ func signToken() error {
|
||||||
|
|
||||||
if isEs() {
|
if isEs() {
|
||||||
if k, ok := key.([]byte); !ok {
|
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 {
|
} else {
|
||||||
key, err = jwt.ParseECPrivateKeyFromPEM(k)
|
key, err = jwt.ParseECPrivateKeyFromPEM(k)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -224,7 +224,7 @@ func signToken() error {
|
||||||
}
|
}
|
||||||
} else if isRs() {
|
} else if isRs() {
|
||||||
if k, ok := key.([]byte); !ok {
|
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 {
|
} else {
|
||||||
key, err = jwt.ParseRSAPrivateKeyFromPEM(k)
|
key, err = jwt.ParseRSAPrivateKeyFromPEM(k)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -233,7 +233,7 @@ func signToken() error {
|
||||||
}
|
}
|
||||||
} else if isEd() {
|
} else if isEd() {
|
||||||
if k, ok := key.([]byte); !ok {
|
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 {
|
} else {
|
||||||
key, err = jwt.ParseEdPrivateKeyFromPEM(k)
|
key, err = jwt.ParseEdPrivateKeyFromPEM(k)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -245,7 +245,7 @@ func signToken() error {
|
||||||
if out, err := token.SignedString(key); err == nil {
|
if out, err := token.SignedString(key); err == nil {
|
||||||
fmt.Println(out)
|
fmt.Println(out)
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("Error signing token: %v", err)
|
return fmt.Errorf("error signing token: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -256,7 +256,7 @@ func showToken() error {
|
||||||
// get the token
|
// get the token
|
||||||
tokData, err := loadData(*flagShow)
|
tokData, err := loadData(*flagShow)
|
||||||
if err != nil {
|
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
|
// trim possible whitespace from token
|
||||||
|
@ -267,18 +267,18 @@ func showToken() error {
|
||||||
|
|
||||||
token, err := jwt.Parse(string(tokData), nil)
|
token, err := jwt.Parse(string(tokData), nil)
|
||||||
if token == nil {
|
if token == nil {
|
||||||
return fmt.Errorf("malformed token: %v", err)
|
return fmt.Errorf("malformed token: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print the token details
|
// Print the token details
|
||||||
fmt.Println("Header:")
|
fmt.Println("Header:")
|
||||||
if err := printJSON(token.Header); err != nil {
|
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:")
|
fmt.Println("Claims:")
|
||||||
if err := printJSON(token.Claims); err != nil {
|
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
|
return nil
|
||||||
|
@ -295,3 +295,19 @@ func isRs() bool {
|
||||||
func isEd() bool {
|
func isEd() bool {
|
||||||
return strings.HasPrefix(strings.ToUpper(*flagAlg), "Ed")
|
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
|
||||||
|
}
|
6
ecdsa.go
6
ecdsa.go
|
@ -13,7 +13,7 @@ var (
|
||||||
ErrECDSAVerification = errors.New("crypto/ecdsa: verification error")
|
ErrECDSAVerification = errors.New("crypto/ecdsa: verification error")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Implements the ECDSA family of signing methods signing methods
|
// SigningMethodECDSA implements the ECDSA family of signing methods.
|
||||||
// Expects *ecdsa.PrivateKey for signing and *ecdsa.PublicKey for verification
|
// Expects *ecdsa.PrivateKey for signing and *ecdsa.PublicKey for verification
|
||||||
type SigningMethodECDSA struct {
|
type SigningMethodECDSA struct {
|
||||||
Name string
|
Name string
|
||||||
|
@ -53,7 +53,7 @@ func (m *SigningMethodECDSA) Alg() string {
|
||||||
return m.Name
|
return m.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the Verify method from SigningMethod
|
// Verify implements token verification for the SigningMethod.
|
||||||
// For this verify method, key must be an ecdsa.PublicKey struct
|
// For this verify method, key must be an ecdsa.PublicKey struct
|
||||||
func (m *SigningMethodECDSA) Verify(signingString, signature string, key interface{}) error {
|
func (m *SigningMethodECDSA) Verify(signingString, signature string, key interface{}) error {
|
||||||
var err error
|
var err error
|
||||||
|
@ -95,7 +95,7 @@ func (m *SigningMethodECDSA) Verify(signingString, signature string, key interfa
|
||||||
return ErrECDSAVerification
|
return ErrECDSAVerification
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the Sign method from SigningMethod
|
// Sign implements token signing for the SigningMethod.
|
||||||
// For this signing method, key must be an ecdsa.PrivateKey struct
|
// For this signing method, key must be an ecdsa.PrivateKey struct
|
||||||
func (m *SigningMethodECDSA) Sign(signingString string, key interface{}) (string, error) {
|
func (m *SigningMethodECDSA) Sign(signingString string, key interface{}) (string, error) {
|
||||||
// Get the key
|
// Get the key
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt"
|
"github.com/golang-jwt/jwt/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ecdsaTestData = []struct {
|
var ecdsaTestData = []struct {
|
||||||
|
|
|
@ -8,11 +8,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrNotECPublicKey = errors.New("Key is not a valid ECDSA public key")
|
ErrNotECPublicKey = errors.New("key is not a valid ECDSA public key")
|
||||||
ErrNotECPrivateKey = errors.New("Key is not a valid ECDSA private key")
|
ErrNotECPrivateKey = errors.New("key is not a valid ECDSA private key")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Parse PEM encoded Elliptic Curve Private Key Structure
|
// ParseECPrivateKeyFromPEM parses a PEM encoded Elliptic Curve Private Key Structure
|
||||||
func ParseECPrivateKeyFromPEM(key []byte) (*ecdsa.PrivateKey, error) {
|
func ParseECPrivateKeyFromPEM(key []byte) (*ecdsa.PrivateKey, error) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ func ParseECPrivateKeyFromPEM(key []byte) (*ecdsa.PrivateKey, error) {
|
||||||
return pkey, nil
|
return pkey, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse PEM encoded PKCS1 or PKCS8 public key
|
// ParseECPublicKeyFromPEM parses a PEM encoded PKCS1 or PKCS8 public key
|
||||||
func ParseECPublicKeyFromPEM(key []byte) (*ecdsa.PublicKey, error) {
|
func ParseECPublicKeyFromPEM(key []byte) (*ecdsa.PublicKey, error) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ var (
|
||||||
ErrEd25519Verification = errors.New("ed25519: verification error")
|
ErrEd25519Verification = errors.New("ed25519: verification error")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Implements the EdDSA family
|
// SigningMethodEd25519 implements the EdDSA family.
|
||||||
// Expects ed25519.PrivateKey for signing and ed25519.PublicKey for verification
|
// Expects ed25519.PrivateKey for signing and ed25519.PublicKey for verification
|
||||||
type SigningMethodEd25519 struct{}
|
type SigningMethodEd25519 struct{}
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ func (m *SigningMethodEd25519) Alg() string {
|
||||||
return "EdDSA"
|
return "EdDSA"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the Verify method from SigningMethod
|
// Verify implements token verification for the SigningMethod.
|
||||||
// For this verify method, key must be an ed25519.PublicKey
|
// For this verify method, key must be an ed25519.PublicKey
|
||||||
func (m *SigningMethodEd25519) Verify(signingString, signature string, key interface{}) error {
|
func (m *SigningMethodEd25519) Verify(signingString, signature string, key interface{}) error {
|
||||||
var err error
|
var err error
|
||||||
|
@ -59,7 +59,7 @@ func (m *SigningMethodEd25519) Verify(signingString, signature string, key inter
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the Sign method from SigningMethod
|
// Sign implements token signing for the SigningMethod.
|
||||||
// For this signing method, key must be an ed25519.PrivateKey
|
// For this signing method, key must be an ed25519.PrivateKey
|
||||||
func (m *SigningMethodEd25519) Sign(signingString string, key interface{}) (string, error) {
|
func (m *SigningMethodEd25519) Sign(signingString string, key interface{}) (string, error) {
|
||||||
var ed25519Key ed25519.PrivateKey
|
var ed25519Key ed25519.PrivateKey
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt"
|
"github.com/golang-jwt/jwt/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ed25519TestData = []struct {
|
var ed25519TestData = []struct {
|
||||||
|
|
|
@ -9,11 +9,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrNotEdPrivateKey = errors.New("Key is not a valid Ed25519 private key")
|
ErrNotEdPrivateKey = errors.New("key is not a valid Ed25519 private key")
|
||||||
ErrNotEdPublicKey = errors.New("Key is not a valid Ed25519 public key")
|
ErrNotEdPublicKey = errors.New("key is not a valid Ed25519 public key")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Parse PEM-encoded Edwards curve private key
|
// ParseEdPrivateKeyFromPEM parses a PEM-encoded Edwards curve private key
|
||||||
func ParseEdPrivateKeyFromPEM(key []byte) (crypto.PrivateKey, error) {
|
func ParseEdPrivateKeyFromPEM(key []byte) (crypto.PrivateKey, error) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ func ParseEdPrivateKeyFromPEM(key []byte) (crypto.PrivateKey, error) {
|
||||||
return pkey, nil
|
return pkey, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse PEM-encoded Edwards curve public key
|
// ParseEdPublicKeyFromPEM parses a PEM-encoded Edwards curve public key
|
||||||
func ParseEdPublicKeyFromPEM(key []byte) (crypto.PublicKey, error) {
|
func ParseEdPublicKeyFromPEM(key []byte) (crypto.PublicKey, error) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ const (
|
||||||
ValidationErrorClaimsInvalid // Generic claims validation error
|
ValidationErrorClaimsInvalid // Generic claims validation error
|
||||||
)
|
)
|
||||||
|
|
||||||
// Helper for constructing a ValidationError with a string error message
|
// NewValidationError is a helper for constructing a ValidationError with a string error message
|
||||||
func NewValidationError(errorText string, errorFlags uint32) *ValidationError {
|
func NewValidationError(errorText string, errorFlags uint32) *ValidationError {
|
||||||
return &ValidationError{
|
return &ValidationError{
|
||||||
text: errorText,
|
text: errorText,
|
||||||
|
@ -35,14 +35,14 @@ func NewValidationError(errorText string, errorFlags uint32) *ValidationError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The error from Parse if token is not valid
|
// ValidationError represents an error from Parse if token is not valid
|
||||||
type ValidationError struct {
|
type ValidationError struct {
|
||||||
Inner error // stores the error returned by external dependencies, i.e.: KeyFunc
|
Inner error // stores the error returned by external dependencies, i.e.: KeyFunc
|
||||||
Errors uint32 // bitfield. see ValidationError... constants
|
Errors uint32 // bitfield. see ValidationError... constants
|
||||||
text string // errors that do not have a valid error just have text
|
text string // errors that do not have a valid error just have text
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validation error is an error type
|
// Error is the implementation of the err interface.
|
||||||
func (e ValidationError) Error() string {
|
func (e ValidationError) Error() string {
|
||||||
if e.Inner != nil {
|
if e.Inner != nil {
|
||||||
return e.Inner.Error()
|
return e.Inner.Error()
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt"
|
"github.com/golang-jwt/jwt/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Example (atypical) using the StandardClaims type by itself to parse a token.
|
// Example (atypical) using the StandardClaims type by itself to parse a token.
|
||||||
|
|
6
hmac.go
6
hmac.go
|
@ -6,7 +6,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Implements the HMAC-SHA family of signing methods signing methods
|
// SigningMethodHMAC implements the HMAC-SHA family of signing methods.
|
||||||
// Expects key type of []byte for both signing and validation
|
// Expects key type of []byte for both signing and validation
|
||||||
type SigningMethodHMAC struct {
|
type SigningMethodHMAC struct {
|
||||||
Name string
|
Name string
|
||||||
|
@ -45,7 +45,7 @@ func (m *SigningMethodHMAC) Alg() string {
|
||||||
return m.Name
|
return m.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the signature of HSXXX tokens. Returns nil if the signature is valid.
|
// Verify implements token verification for the SigningMethod. Returns nil if the signature is valid.
|
||||||
func (m *SigningMethodHMAC) Verify(signingString, signature string, key interface{}) error {
|
func (m *SigningMethodHMAC) Verify(signingString, signature string, key interface{}) error {
|
||||||
// Verify the key is the right type
|
// Verify the key is the right type
|
||||||
keyBytes, ok := key.([]byte)
|
keyBytes, ok := key.([]byte)
|
||||||
|
@ -77,7 +77,7 @@ func (m *SigningMethodHMAC) Verify(signingString, signature string, key interfac
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the Sign method from SigningMethod for this signing method.
|
// Sign implements token signing for the SigningMethod.
|
||||||
// Key must be []byte
|
// Key must be []byte
|
||||||
func (m *SigningMethodHMAC) Sign(signingString string, key interface{}) (string, error) {
|
func (m *SigningMethodHMAC) Sign(signingString string, key interface{}) (string, error) {
|
||||||
if keyBytes, ok := key.([]byte); ok {
|
if keyBytes, ok := key.([]byte); ok {
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt"
|
"github.com/golang-jwt/jwt/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
// For HMAC signing method, the key can be any []byte. It is recommended to generate
|
// For HMAC signing method, the key can be any []byte. It is recommended to generate
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt"
|
"github.com/golang-jwt/jwt/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
var hmacTestData = []struct {
|
var hmacTestData = []struct {
|
||||||
|
|
|
@ -16,8 +16,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt"
|
"github.com/golang-jwt/jwt/v4"
|
||||||
"github.com/golang-jwt/jwt/request"
|
"github.com/golang-jwt/jwt/v4/request"
|
||||||
)
|
)
|
||||||
|
|
||||||
// location of the files used for signing and verification
|
// location of the files used for signing and verification
|
||||||
|
@ -30,11 +30,6 @@ var (
|
||||||
verifyKey *rsa.PublicKey
|
verifyKey *rsa.PublicKey
|
||||||
signKey *rsa.PrivateKey
|
signKey *rsa.PrivateKey
|
||||||
serverPort int
|
serverPort int
|
||||||
// storing sample username/password pairs
|
|
||||||
// don't do this on a real server
|
|
||||||
users = map[string]string{
|
|
||||||
"test": "known",
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// read the key files before starting http handlers
|
// read the key files before starting http handlers
|
||||||
|
@ -65,8 +60,6 @@ func init() {
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
var start func()
|
|
||||||
|
|
||||||
func fatal(err error) {
|
func fatal(err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
@ -199,11 +192,11 @@ func authHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
// only accessible with a valid token
|
// only accessible with a valid token
|
||||||
func restrictedHandler(w http.ResponseWriter, r *http.Request) {
|
func restrictedHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
// Get token from request
|
// Get token from request
|
||||||
token, err := request.ParseFromRequestWithClaims(r, request.OAuth2Extractor, &CustomClaimsExample{}, func(token *jwt.Token) (interface{}, error) {
|
token, err := request.ParseFromRequest(r, request.OAuth2Extractor, func(token *jwt.Token) (interface{}, error) {
|
||||||
// since we only use the one private key to sign the tokens,
|
// since we only use the one private key to sign the tokens,
|
||||||
// we also only use its public counter part to verify
|
// we also only use its public counter part to verify
|
||||||
return verifyKey, nil
|
return verifyKey, nil
|
||||||
})
|
}, request.WithClaims(&CustomClaimsExample{}))
|
||||||
|
|
||||||
// If the token is missing or invalid, return error
|
// If the token is missing or invalid, return error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -214,5 +207,4 @@ func restrictedHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
// Token is valid
|
// Token is valid
|
||||||
fmt.Fprintln(w, "Welcome,", token.Claims.(*CustomClaimsExample).Name)
|
fmt.Fprintln(w, "Welcome,", token.Claims.(*CustomClaimsExample).Name)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
// "fmt"
|
// "fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Claims type that uses the map[string]interface{} for JSON decoding
|
// MapClaims is a claims type that uses the map[string]interface{} for JSON decoding.
|
||||||
// This is the default claims type if you don't supply one
|
// This is the default claims type if you don't supply one
|
||||||
type MapClaims map[string]interface{}
|
type MapClaims map[string]interface{}
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ func (m MapClaims) VerifyAudience(cmp string, req bool) bool {
|
||||||
return verifyAud(aud, cmp, req)
|
return verifyAud(aud, 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
|
// If required is false, this method will return true if the value matches or is unset
|
||||||
func (m MapClaims) VerifyExpiresAt(cmp int64, req bool) bool {
|
func (m MapClaims) VerifyExpiresAt(cmp int64, req bool) bool {
|
||||||
exp, ok := m["exp"]
|
exp, ok := m["exp"]
|
||||||
|
@ -48,7 +48,7 @@ func (m MapClaims) VerifyExpiresAt(cmp int64, req bool) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
// If required is false, this method will return true if the value matches or is unset
|
||||||
func (m MapClaims) VerifyIssuedAt(cmp int64, req bool) bool {
|
func (m MapClaims) VerifyIssuedAt(cmp int64, req bool) bool {
|
||||||
iat, ok := m["iat"]
|
iat, ok := m["iat"]
|
||||||
|
@ -65,14 +65,14 @@ func (m MapClaims) VerifyIssuedAt(cmp int64, req bool) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
// If required is false, this method will return true if the value matches or is unset
|
||||||
func (m MapClaims) VerifyIssuer(cmp string, req bool) bool {
|
func (m MapClaims) VerifyIssuer(cmp string, req bool) bool {
|
||||||
iss, _ := m["iss"].(string)
|
iss, _ := m["iss"].(string)
|
||||||
return verifyIss(iss, cmp, req)
|
return verifyIss(iss, 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
|
// If required is false, this method will return true if the value matches or is unset
|
||||||
func (m MapClaims) VerifyNotBefore(cmp int64, req bool) bool {
|
func (m MapClaims) VerifyNotBefore(cmp int64, req bool) bool {
|
||||||
nbf, ok := m["nbf"]
|
nbf, ok := m["nbf"]
|
||||||
|
@ -89,7 +89,7 @@ func (m MapClaims) VerifyNotBefore(cmp int64, req bool) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validates time based claims "exp, iat, nbf".
|
// Valid calidates time based claims "exp, iat, nbf".
|
||||||
// There is no accounting for clock skew.
|
// There is no accounting for clock skew.
|
||||||
// As well, if any of the above claims are not in the token, it will still
|
// As well, if any of the above claims are not in the token, it will still
|
||||||
// be considered a valid claim.
|
// be considered a valid claim.
|
||||||
|
|
2
none.go
2
none.go
|
@ -1,6 +1,6 @@
|
||||||
package jwt
|
package jwt
|
||||||
|
|
||||||
// Implements the none signing method. This is required by the spec
|
// SigningMethodNone implements the none signing method. This is required by the spec
|
||||||
// but you probably should never use it.
|
// but you probably should never use it.
|
||||||
var SigningMethodNone *signingMethodNone
|
var SigningMethodNone *signingMethodNone
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt"
|
"github.com/golang-jwt/jwt/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
var noneTestData = []struct {
|
var noneTestData = []struct {
|
||||||
|
|
12
parser.go
12
parser.go
|
@ -13,7 +13,7 @@ type Parser struct {
|
||||||
SkipClaimsValidation bool // Skip claims validation during token parsing
|
SkipClaimsValidation bool // Skip claims validation during token parsing
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse, validate, and return a token.
|
// Parse parses, validates, and returns a token.
|
||||||
// keyFunc will receive the parsed token and should return the key for validating.
|
// keyFunc will receive the parsed token and should return the key for validating.
|
||||||
// If everything is kosher, err will be nil
|
// If everything is kosher, err will be nil
|
||||||
func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) {
|
func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) {
|
||||||
|
@ -87,12 +87,12 @@ func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyf
|
||||||
return token, vErr
|
return token, vErr
|
||||||
}
|
}
|
||||||
|
|
||||||
// WARNING: Don't use this method unless you know what you're doing
|
// ParseUnverified parses the token but doesn't validate the signature.
|
||||||
//
|
//
|
||||||
// This method parses the token but doesn't validate the signature. It's only
|
// WARNING: Don't use this method unless you know what you're doing.
|
||||||
// ever useful in cases where you know the signature is valid (because it has
|
//
|
||||||
// been checked previously in the stack) and you want to extract values from
|
// It's only ever useful in cases where you know the signature is valid (because it has
|
||||||
// it.
|
// been checked previously in the stack) and you want to extract values from it.
|
||||||
func (p *Parser) ParseUnverified(tokenString string, claims Claims) (token *Token, parts []string, err error) {
|
func (p *Parser) ParseUnverified(tokenString string, claims Claims) (token *Token, parts []string, err error) {
|
||||||
parts = strings.Split(tokenString, ".")
|
parts = strings.Split(tokenString, ".")
|
||||||
if len(parts) != 3 {
|
if len(parts) != 3 {
|
||||||
|
|
|
@ -8,17 +8,17 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt"
|
"github.com/golang-jwt/jwt/v4"
|
||||||
"github.com/golang-jwt/jwt/test"
|
"github.com/golang-jwt/jwt/v4/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
var keyFuncError error = fmt.Errorf("error loading key")
|
var errKeyFuncError error = fmt.Errorf("error loading key")
|
||||||
|
|
||||||
var (
|
var (
|
||||||
jwtTestDefaultKey *rsa.PublicKey
|
jwtTestDefaultKey *rsa.PublicKey
|
||||||
defaultKeyFunc jwt.Keyfunc = func(t *jwt.Token) (interface{}, error) { return jwtTestDefaultKey, nil }
|
defaultKeyFunc jwt.Keyfunc = func(t *jwt.Token) (interface{}, error) { return jwtTestDefaultKey, nil }
|
||||||
emptyKeyFunc jwt.Keyfunc = func(t *jwt.Token) (interface{}, error) { return nil, nil }
|
emptyKeyFunc jwt.Keyfunc = func(t *jwt.Token) (interface{}, error) { return nil, nil }
|
||||||
errorKeyFunc jwt.Keyfunc = func(t *jwt.Token) (interface{}, error) { return nil, keyFuncError }
|
errorKeyFunc jwt.Keyfunc = func(t *jwt.Token) (interface{}, error) { return nil, errKeyFuncError }
|
||||||
nilKeyFunc jwt.Keyfunc = nil
|
nilKeyFunc jwt.Keyfunc = nil
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -236,8 +236,8 @@ func TestParser_Parse(t *testing.T) {
|
||||||
t.Errorf("[%v] Errors don't match expectation. %v != %v", data.name, e, data.errors)
|
t.Errorf("[%v] Errors don't match expectation. %v != %v", data.name, e, data.errors)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err.Error() == keyFuncError.Error() && ve.Inner != keyFuncError {
|
if err.Error() == errKeyFuncError.Error() && ve.Inner != errKeyFuncError {
|
||||||
t.Errorf("[%v] Inner error does not match expectation. %v != %v", data.name, ve.Inner, keyFuncError)
|
t.Errorf("[%v] Inner error does not match expectation. %v != %v", data.name, ve.Inner, errKeyFuncError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,15 +10,15 @@ var (
|
||||||
ErrNoTokenInRequest = errors.New("no token present in request")
|
ErrNoTokenInRequest = errors.New("no token present in request")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Interface for extracting a token from an HTTP request.
|
// Extractor is an interface for extracting a token from an HTTP request.
|
||||||
// The ExtractToken method should return a token string or an error.
|
// The ExtractToken method should return a token string or an error.
|
||||||
// If no token is present, you must return ErrNoTokenInRequest.
|
// If no token is present, you must return ErrNoTokenInRequest.
|
||||||
type Extractor interface {
|
type Extractor interface {
|
||||||
ExtractToken(*http.Request) (string, error)
|
ExtractToken(*http.Request) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extractor for finding a token in a header. Looks at each specified
|
// HeaderExtractor is an extractor for finding a token in a header.
|
||||||
// header in order until there's a match
|
// Looks at each specified header in order until there's a match
|
||||||
type HeaderExtractor []string
|
type HeaderExtractor []string
|
||||||
|
|
||||||
func (e HeaderExtractor) ExtractToken(req *http.Request) (string, error) {
|
func (e HeaderExtractor) ExtractToken(req *http.Request) (string, error) {
|
||||||
|
@ -31,7 +31,7 @@ func (e HeaderExtractor) ExtractToken(req *http.Request) (string, error) {
|
||||||
return "", ErrNoTokenInRequest
|
return "", ErrNoTokenInRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract token from request arguments. This includes a POSTed form or
|
// ArgumentExtractor extracts a token from request arguments. This includes a POSTed form or
|
||||||
// GET URL arguments. Argument names are tried in order until there's a match.
|
// GET URL arguments. Argument names are tried in order until there's a match.
|
||||||
// This extractor calls `ParseMultipartForm` on the request
|
// This extractor calls `ParseMultipartForm` on the request
|
||||||
type ArgumentExtractor []string
|
type ArgumentExtractor []string
|
||||||
|
@ -50,7 +50,7 @@ func (e ArgumentExtractor) ExtractToken(req *http.Request) (string, error) {
|
||||||
return "", ErrNoTokenInRequest
|
return "", ErrNoTokenInRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tries Extractors in order until one returns a token string or an error occurs
|
// MultiExtractor tries Extractors in order until one returns a token string or an error occurs
|
||||||
type MultiExtractor []Extractor
|
type MultiExtractor []Extractor
|
||||||
|
|
||||||
func (e MultiExtractor) ExtractToken(req *http.Request) (string, error) {
|
func (e MultiExtractor) ExtractToken(req *http.Request) (string, error) {
|
||||||
|
@ -65,7 +65,7 @@ func (e MultiExtractor) ExtractToken(req *http.Request) (string, error) {
|
||||||
return "", ErrNoTokenInRequest
|
return "", ErrNoTokenInRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrap an Extractor in this to post-process the value before it's handed off.
|
// PostExtractionFilter wraps an Extractor in this to post-process the value before it's handed off.
|
||||||
// See AuthorizationHeaderExtractor for an example
|
// See AuthorizationHeaderExtractor for an example
|
||||||
type PostExtractionFilter struct {
|
type PostExtractionFilter struct {
|
||||||
Extractor
|
Extractor
|
||||||
|
|
|
@ -13,14 +13,14 @@ func stripBearerPrefixFromTokenString(tok string) (string, error) {
|
||||||
return tok, nil
|
return tok, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract bearer token from Authorization header
|
// AuthorizationHeaderExtractor extracts a bearer token from Authorization header
|
||||||
// Uses PostExtractionFilter to strip "Bearer " prefix from header
|
// Uses PostExtractionFilter to strip "Bearer " prefix from header
|
||||||
var AuthorizationHeaderExtractor = &PostExtractionFilter{
|
var AuthorizationHeaderExtractor = &PostExtractionFilter{
|
||||||
HeaderExtractor{"Authorization"},
|
HeaderExtractor{"Authorization"},
|
||||||
stripBearerPrefixFromTokenString,
|
stripBearerPrefixFromTokenString,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extractor for OAuth2 access tokens. Looks in 'Authorization'
|
// OAuth2Extractor is an Extractor for OAuth2 access tokens. Looks in 'Authorization'
|
||||||
// header then 'access_token' argument for a token.
|
// header then 'access_token' argument for a token.
|
||||||
var OAuth2Extractor = &MultiExtractor{
|
var OAuth2Extractor = &MultiExtractor{
|
||||||
AuthorizationHeaderExtractor,
|
AuthorizationHeaderExtractor,
|
||||||
|
|
|
@ -3,10 +3,10 @@ package request
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt"
|
"github.com/golang-jwt/jwt/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Extract and parse a JWT token from an HTTP request.
|
// ParseFromRequest extracts and parses a JWT token from an HTTP request.
|
||||||
// This behaves the same as Parse, but accepts a request and an extractor
|
// This behaves the same as Parse, but accepts a request and an extractor
|
||||||
// instead of a token string. The Extractor interface allows you to define
|
// instead of a token string. The Extractor interface allows you to define
|
||||||
// the logic for extracting a token. Several useful implementations are provided.
|
// the logic for extracting a token. Several useful implementations are provided.
|
||||||
|
@ -39,8 +39,9 @@ func ParseFromRequest(req *http.Request, extractor Extractor, keyFunc jwt.Keyfun
|
||||||
return p.parser.ParseWithClaims(tokenString, p.claims, keyFunc)
|
return p.parser.ParseWithClaims(tokenString, p.claims, keyFunc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseFromRequest but with custom Claims type
|
// ParseFromRequestWithClaims is an alias for ParseFromRequest but with custom Claims type.
|
||||||
// DEPRECATED: use ParseFromRequest and the WithClaims option
|
//
|
||||||
|
// Deprecated: use ParseFromRequest and the WithClaims option
|
||||||
func ParseFromRequestWithClaims(req *http.Request, extractor Extractor, claims jwt.Claims, keyFunc jwt.Keyfunc) (token *jwt.Token, err error) {
|
func ParseFromRequestWithClaims(req *http.Request, extractor Extractor, claims jwt.Claims, keyFunc jwt.Keyfunc) (token *jwt.Token, err error) {
|
||||||
return ParseFromRequest(req, extractor, keyFunc, WithClaims(claims))
|
return ParseFromRequest(req, extractor, keyFunc, WithClaims(claims))
|
||||||
}
|
}
|
||||||
|
@ -54,14 +55,14 @@ type fromRequestParser struct {
|
||||||
|
|
||||||
type ParseFromRequestOption func(*fromRequestParser)
|
type ParseFromRequestOption func(*fromRequestParser)
|
||||||
|
|
||||||
// Parse with custom claims
|
// WithClaims parses with custom claims
|
||||||
func WithClaims(claims jwt.Claims) ParseFromRequestOption {
|
func WithClaims(claims jwt.Claims) ParseFromRequestOption {
|
||||||
return func(p *fromRequestParser) {
|
return func(p *fromRequestParser) {
|
||||||
p.claims = claims
|
p.claims = claims
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse using a custom parser
|
// WithParser parses using a custom parser
|
||||||
func WithParser(parser *jwt.Parser) ParseFromRequestOption {
|
func WithParser(parser *jwt.Parser) ParseFromRequestOption {
|
||||||
return func(p *fromRequestParser) {
|
return func(p *fromRequestParser) {
|
||||||
p.parser = parser
|
p.parser = parser
|
||||||
|
|
|
@ -8,8 +8,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt"
|
"github.com/golang-jwt/jwt/v4"
|
||||||
"github.com/golang-jwt/jwt/test"
|
"github.com/golang-jwt/jwt/v4/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
var requestTestData = []struct {
|
var requestTestData = []struct {
|
||||||
|
|
6
rsa.go
6
rsa.go
|
@ -6,7 +6,7 @@ import (
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Implements the RSA family of signing methods signing methods
|
// SigningMethodRSA implements the RSA family of signing methods.
|
||||||
// Expects *rsa.PrivateKey for signing and *rsa.PublicKey for validation
|
// Expects *rsa.PrivateKey for signing and *rsa.PublicKey for validation
|
||||||
type SigningMethodRSA struct {
|
type SigningMethodRSA struct {
|
||||||
Name string
|
Name string
|
||||||
|
@ -44,7 +44,7 @@ func (m *SigningMethodRSA) Alg() string {
|
||||||
return m.Name
|
return m.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the Verify method from SigningMethod
|
// Verify implements token verification for the SigningMethod
|
||||||
// For this signing method, must be an *rsa.PublicKey structure.
|
// For this signing method, must be an *rsa.PublicKey structure.
|
||||||
func (m *SigningMethodRSA) Verify(signingString, signature string, key interface{}) error {
|
func (m *SigningMethodRSA) Verify(signingString, signature string, key interface{}) error {
|
||||||
var err error
|
var err error
|
||||||
|
@ -73,7 +73,7 @@ func (m *SigningMethodRSA) Verify(signingString, signature string, key interface
|
||||||
return rsa.VerifyPKCS1v15(rsaKey, m.Hash, hasher.Sum(nil), sig)
|
return rsa.VerifyPKCS1v15(rsaKey, m.Hash, hasher.Sum(nil), sig)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the Sign method from SigningMethod
|
// Sign implements token signing for the SigningMethod
|
||||||
// For this signing method, must be an *rsa.PrivateKey structure.
|
// For this signing method, must be an *rsa.PrivateKey structure.
|
||||||
func (m *SigningMethodRSA) Sign(signingString string, key interface{}) (string, error) {
|
func (m *SigningMethodRSA) Sign(signingString string, key interface{}) (string, error) {
|
||||||
var rsaKey *rsa.PrivateKey
|
var rsaKey *rsa.PrivateKey
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Implements the RSAPSS family of signing methods signing methods
|
// SigningMethodRSAPSS implements the RSAPSS family of signing methods signing methods
|
||||||
type SigningMethodRSAPSS struct {
|
type SigningMethodRSAPSS struct {
|
||||||
*SigningMethodRSA
|
*SigningMethodRSA
|
||||||
Options *rsa.PSSOptions
|
Options *rsa.PSSOptions
|
||||||
|
@ -79,7 +79,7 @@ func init() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the Verify method from SigningMethod
|
// Verify implements token verification for the SigningMethod.
|
||||||
// For this verify method, key must be an rsa.PublicKey struct
|
// For this verify method, key must be an rsa.PublicKey struct
|
||||||
func (m *SigningMethodRSAPSS) Verify(signingString, signature string, key interface{}) error {
|
func (m *SigningMethodRSAPSS) Verify(signingString, signature string, key interface{}) error {
|
||||||
var err error
|
var err error
|
||||||
|
@ -113,7 +113,7 @@ func (m *SigningMethodRSAPSS) Verify(signingString, signature string, key interf
|
||||||
return rsa.VerifyPSS(rsaKey, m.Hash, hasher.Sum(nil), sig, opts)
|
return rsa.VerifyPSS(rsaKey, m.Hash, hasher.Sum(nil), sig, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the Sign method from SigningMethod
|
// Sign implements token signing for the SigningMethod.
|
||||||
// For this signing method, key must be an rsa.PrivateKey struct
|
// For this signing method, key must be an rsa.PrivateKey struct
|
||||||
func (m *SigningMethodRSAPSS) Sign(signingString string, key interface{}) (string, error) {
|
func (m *SigningMethodRSAPSS) Sign(signingString string, key interface{}) (string, error) {
|
||||||
var rsaKey *rsa.PrivateKey
|
var rsaKey *rsa.PrivateKey
|
||||||
|
|
|
@ -9,8 +9,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt"
|
"github.com/golang-jwt/jwt/v4"
|
||||||
"github.com/golang-jwt/jwt/test"
|
"github.com/golang-jwt/jwt/v4/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
var rsaPSSTestData = []struct {
|
var rsaPSSTestData = []struct {
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt"
|
"github.com/golang-jwt/jwt/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
var rsaTestData = []struct {
|
var rsaTestData = []struct {
|
||||||
|
|
16
rsa_utils.go
16
rsa_utils.go
|
@ -8,12 +8,12 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrKeyMustBePEMEncoded = errors.New("Invalid Key: Key must be a PEM encoded PKCS1 or PKCS8 key")
|
ErrKeyMustBePEMEncoded = errors.New("invalid key: Key must be a PEM encoded PKCS1 or PKCS8 key")
|
||||||
ErrNotRSAPrivateKey = errors.New("Key is not a valid RSA private key")
|
ErrNotRSAPrivateKey = errors.New("key is not a valid RSA private key")
|
||||||
ErrNotRSAPublicKey = errors.New("Key is not a valid RSA public key")
|
ErrNotRSAPublicKey = errors.New("key is not a valid RSA public key")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Parse PEM encoded PKCS1 or PKCS8 private key
|
// ParseRSAPrivateKeyFromPEM parses a PEM encoded PKCS1 or PKCS8 private key
|
||||||
func ParseRSAPrivateKeyFromPEM(key []byte) (*rsa.PrivateKey, error) {
|
func ParseRSAPrivateKeyFromPEM(key []byte) (*rsa.PrivateKey, error) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
@ -39,7 +39,11 @@ func ParseRSAPrivateKeyFromPEM(key []byte) (*rsa.PrivateKey, error) {
|
||||||
return pkey, nil
|
return pkey, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse PEM encoded PKCS1 or PKCS8 private key protected with password
|
// ParseRSAPrivateKeyFromPEMWithPassword parses a PEM encoded PKCS1 or PKCS8 private key protected with password
|
||||||
|
//
|
||||||
|
// Deprecated: This function is deprecated and should not be used anymore. It uses the deprecated x509.DecryptPEMBlock
|
||||||
|
// function, which was deprecated since RFC 1423 is regarded insecure by design. Unfortunately, there is no alternative
|
||||||
|
// in the Go standard library for now. See https://github.com/golang/go/issues/8860.
|
||||||
func ParseRSAPrivateKeyFromPEMWithPassword(key []byte, password string) (*rsa.PrivateKey, error) {
|
func ParseRSAPrivateKeyFromPEMWithPassword(key []byte, password string) (*rsa.PrivateKey, error) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
@ -71,7 +75,7 @@ func ParseRSAPrivateKeyFromPEMWithPassword(key []byte, password string) (*rsa.Pr
|
||||||
return pkey, nil
|
return pkey, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse PEM encoded PKCS1 or PKCS8 public key
|
// ParseRSAPublicKeyFromPEM parses a PEM encoded PKCS1 or PKCS8 public key
|
||||||
func ParseRSAPublicKeyFromPEM(key []byte) (*rsa.PublicKey, error) {
|
func ParseRSAPublicKeyFromPEM(key []byte) (*rsa.PublicKey, error) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
|
|
@ -7,14 +7,14 @@ import (
|
||||||
var signingMethods = map[string]func() SigningMethod{}
|
var signingMethods = map[string]func() SigningMethod{}
|
||||||
var signingMethodLock = new(sync.RWMutex)
|
var signingMethodLock = new(sync.RWMutex)
|
||||||
|
|
||||||
// Implement SigningMethod to add new methods for signing or verifying tokens.
|
// SigningMethod can be used add new methods for signing or verifying tokens.
|
||||||
type SigningMethod interface {
|
type SigningMethod interface {
|
||||||
Verify(signingString, signature string, key interface{}) error // Returns nil if signature is valid
|
Verify(signingString, signature string, key interface{}) error // Returns nil if signature is valid
|
||||||
Sign(signingString string, key interface{}) (string, error) // Returns encoded signature or error
|
Sign(signingString string, key interface{}) (string, error) // Returns encoded signature or error
|
||||||
Alg() string // returns the alg identifier for this method (example: 'HS256')
|
Alg() string // returns the alg identifier for this method (example: 'HS256')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register the "alg" name and a factory function for signing method.
|
// RegisterSigningMethod registers the "alg" name and a factory function for signing method.
|
||||||
// This is typically done during init() in the method's implementation
|
// This is typically done during init() in the method's implementation
|
||||||
func RegisterSigningMethod(alg string, f func() SigningMethod) {
|
func RegisterSigningMethod(alg string, f func() SigningMethod) {
|
||||||
signingMethodLock.Lock()
|
signingMethodLock.Lock()
|
||||||
|
@ -23,7 +23,7 @@ func RegisterSigningMethod(alg string, f func() SigningMethod) {
|
||||||
signingMethods[alg] = f
|
signingMethods[alg] = f
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a signing method from an "alg" string
|
// GetSigningMethod retrieves a signing method from an "alg" string
|
||||||
func GetSigningMethod(alg string) (method SigningMethod) {
|
func GetSigningMethod(alg string) (method SigningMethod) {
|
||||||
signingMethodLock.RLock()
|
signingMethodLock.RLock()
|
||||||
defer signingMethodLock.RUnlock()
|
defer signingMethodLock.RUnlock()
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
checks = ["all", "-ST1000", "-ST1003", "-ST1016", "-ST1023"]
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt"
|
"github.com/golang-jwt/jwt/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
func LoadRSAPrivateKeyFromDisk(location string) *rsa.PrivateKey {
|
func LoadRSAPrivateKeyFromDisk(location string) *rsa.PrivateKey {
|
||||||
|
|
22
token.go
22
token.go
|
@ -12,13 +12,13 @@ import (
|
||||||
// server uses a different time zone than your tokens.
|
// server uses a different time zone than your tokens.
|
||||||
var TimeFunc = time.Now
|
var TimeFunc = time.Now
|
||||||
|
|
||||||
// Parse methods use this callback function to supply
|
// Keyfunc will be used by the Parse methods as a callback function to supply
|
||||||
// the key for verification. The function receives the parsed,
|
// the key for verification. The function receives the parsed,
|
||||||
// but unverified Token. This allows you to use properties in the
|
// but unverified Token. This allows you to use properties in the
|
||||||
// Header of the token (such as `kid`) to identify which key to use.
|
// Header of the token (such as `kid`) to identify which key to use.
|
||||||
type Keyfunc func(*Token) (interface{}, error)
|
type Keyfunc func(*Token) (interface{}, error)
|
||||||
|
|
||||||
// A JWT Token. Different fields will be used depending on whether you're
|
// Token represents a JWT Token. Different fields will be used depending on whether you're
|
||||||
// creating or parsing/verifying a token.
|
// creating or parsing/verifying a token.
|
||||||
type Token struct {
|
type Token struct {
|
||||||
Raw string // The raw token. Populated when you Parse a token
|
Raw string // The raw token. Populated when you Parse a token
|
||||||
|
@ -29,7 +29,7 @@ type Token struct {
|
||||||
Valid bool // Is the token valid? Populated when you Parse/Verify a token
|
Valid bool // Is the token valid? Populated when you Parse/Verify a token
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new Token. Takes a signing method
|
// New creates a new Token. Takes a signing method
|
||||||
func New(method SigningMethod) *Token {
|
func New(method SigningMethod) *Token {
|
||||||
return NewWithClaims(method, MapClaims{})
|
return NewWithClaims(method, MapClaims{})
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ func NewWithClaims(method SigningMethod, claims Claims) *Token {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the complete, signed token
|
// SignedString retrieves the complete, signed token
|
||||||
func (t *Token) SignedString(key interface{}) (string, error) {
|
func (t *Token) SignedString(key interface{}) (string, error) {
|
||||||
var sig, sstr string
|
var sig, sstr string
|
||||||
var err error
|
var err error
|
||||||
|
@ -58,7 +58,7 @@ func (t *Token) SignedString(key interface{}) (string, error) {
|
||||||
return strings.Join([]string{sstr, sig}, "."), nil
|
return strings.Join([]string{sstr, sig}, "."), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate the signing string. This is the
|
// SigningString generates the signing string. This is the
|
||||||
// most expensive part of the whole deal. Unless you
|
// most expensive part of the whole deal. Unless you
|
||||||
// need this for something special, just go straight for
|
// need this for something special, just go straight for
|
||||||
// the SignedString.
|
// the SignedString.
|
||||||
|
@ -82,7 +82,7 @@ func (t *Token) SigningString() (string, error) {
|
||||||
return strings.Join(parts, "."), nil
|
return strings.Join(parts, "."), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse, validate, and return a token.
|
// Parse parses, validates, and returns a token.
|
||||||
// keyFunc will receive the parsed token and should return the key for validating.
|
// keyFunc will receive the parsed token and should return the key for validating.
|
||||||
// If everything is kosher, err will be nil
|
// If everything is kosher, err will be nil
|
||||||
func Parse(tokenString string, keyFunc Keyfunc) (*Token, error) {
|
func Parse(tokenString string, keyFunc Keyfunc) (*Token, error) {
|
||||||
|
@ -93,12 +93,18 @@ func ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token
|
||||||
return new(Parser).ParseWithClaims(tokenString, claims, keyFunc)
|
return new(Parser).ParseWithClaims(tokenString, claims, keyFunc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encode JWT specific base64url encoding with padding stripped
|
// EncodeSegment encodes a JWT specific base64url encoding with padding stripped
|
||||||
|
//
|
||||||
|
// Deprecated: In a future release, we will demote this function to a non-exported function, since it
|
||||||
|
// should only be used internally
|
||||||
func EncodeSegment(seg []byte) string {
|
func EncodeSegment(seg []byte) string {
|
||||||
return base64.RawURLEncoding.EncodeToString(seg)
|
return base64.RawURLEncoding.EncodeToString(seg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode JWT specific base64url encoding with padding stripped
|
// DecodeSegment decodes a JWT specific base64url encoding with padding stripped
|
||||||
|
//
|
||||||
|
// Deprecated: In a future release, we will demote this function to a non-exported function, since it
|
||||||
|
// should only be used internally
|
||||||
func DecodeSegment(seg string) ([]byte, error) {
|
func DecodeSegment(seg string) ([]byte, error) {
|
||||||
return base64.RawURLEncoding.DecodeString(seg)
|
return base64.RawURLEncoding.DecodeString(seg)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue