forked from mirror/jwt
Compare commits
6 Commits
compat-tes
...
main
Author | SHA1 | Date |
---|---|---|
re | 29918af7f7 | |
Alexander Yastrebov | 9358574a7a | |
Christian Banse | 2f0984a28b | |
Christian Banse | 2101c1f4bc | |
Krouton | 35053d4e20 | |
Jacob Kopczynski | 0c4e387985 |
|
@ -33,6 +33,8 @@ jobs:
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: "${{ matrix.go }}"
|
go-version: "${{ matrix.go }}"
|
||||||
|
check-latest: true
|
||||||
|
cache: true
|
||||||
- name: Check Go code formatting
|
- name: Check Go code formatting
|
||||||
run: |
|
run: |
|
||||||
if [ "$(gofmt -s -l . | wc -l)" -gt 0 ]; then
|
if [ "$(gofmt -s -l . | wc -l)" -gt 0 ]; then
|
||||||
|
@ -42,6 +44,7 @@ jobs:
|
||||||
fi
|
fi
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
|
go install github.com/mfridman/tparse@latest
|
||||||
go vet ./...
|
go vet ./...
|
||||||
go test -v ./...
|
go test -v -race -count=1 -json -coverpkg=$(go list ./...) ./... | tparse -follow -notests
|
||||||
go build ./...
|
go build ./...
|
||||||
|
|
|
@ -2,18 +2,18 @@
|
||||||
|
|
||||||
Starting from [v4.0.0](https://github.com/golang-jwt/jwt/releases/tag/v4.0.0), the import path will be:
|
Starting from [v4.0.0](https://github.com/golang-jwt/jwt/releases/tag/v4.0.0), the import path will be:
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt/v4"
|
"git.internal/re/jwt/v4"
|
||||||
|
|
||||||
The `/v4` version will be backwards compatible with existing `v3.x.y` tags in this repo, as well as
|
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
|
`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.
|
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`.
|
You can replace all occurrences of `github.com/dgrijalva/jwt-go` or `github.com/golang-jwt/jwt` with `git.internal/re/jwt/v4`, either manually or by using tools such as `sed` or `gofmt`.
|
||||||
|
|
||||||
And then you'd typically run:
|
And then you'd typically run:
|
||||||
|
|
||||||
```
|
```
|
||||||
go get github.com/golang-jwt/jwt/v4
|
go get git.internal/re/jwt/v4
|
||||||
go mod tidy
|
go mod tidy
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
24
README.md
24
README.md
|
@ -1,7 +1,7 @@
|
||||||
# jwt-go
|
# jwt-go
|
||||||
|
|
||||||
[![build](https://github.com/golang-jwt/jwt/actions/workflows/build.yml/badge.svg)](https://github.com/golang-jwt/jwt/actions/workflows/build.yml)
|
[![build](https://github.com/golang-jwt/jwt/actions/workflows/build.yml/badge.svg)](https://github.com/golang-jwt/jwt/actions/workflows/build.yml)
|
||||||
[![Go Reference](https://pkg.go.dev/badge/github.com/golang-jwt/jwt/v4.svg)](https://pkg.go.dev/github.com/golang-jwt/jwt/v4)
|
[![Go Reference](https://pkg.go.dev/badge/git.internal/re/jwt/v4.svg)](https://pkg.go.dev/git.internal/re/jwt/v4)
|
||||||
|
|
||||||
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).
|
||||||
|
|
||||||
|
@ -41,22 +41,22 @@ This library supports the parsing and verification as well as the generation and
|
||||||
1. To install the jwt package, you first need to have [Go](https://go.dev/doc/install) installed, then you can use the command below to add `jwt-go` as a dependency in your Go program.
|
1. To install the jwt package, you first need to have [Go](https://go.dev/doc/install) installed, then you can use the command below to add `jwt-go` as a dependency in your Go program.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
go get -u github.com/golang-jwt/jwt/v4
|
go get -u git.internal/re/jwt/v4
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Import it in your code:
|
2. Import it in your code:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/golang-jwt/jwt/v4"
|
import "git.internal/re/jwt/v4"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
See [the project documentation](https://pkg.go.dev/github.com/golang-jwt/jwt/v4) for examples of usage:
|
See [the project documentation](https://pkg.go.dev/git.internal/re/jwt/v4) for examples of usage:
|
||||||
|
|
||||||
* [Simple example of parsing and validating a token](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#example-Parse-Hmac)
|
* [Simple example of parsing and validating a token](https://pkg.go.dev/git.internal/re/jwt/v4#example-Parse-Hmac)
|
||||||
* [Simple example of building and signing a token](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#example-New-Hmac)
|
* [Simple example of building and signing a token](https://pkg.go.dev/git.internal/re/jwt/v4#example-New-Hmac)
|
||||||
* [Directory of Examples](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#pkg-examples)
|
* [Directory of Examples](https://pkg.go.dev/git.internal/re/jwt/v4#pkg-examples)
|
||||||
|
|
||||||
## Extensions
|
## Extensions
|
||||||
|
|
||||||
|
@ -110,10 +110,10 @@ Asymmetric signing methods, such as RSA, use different keys for signing and veri
|
||||||
|
|
||||||
Each signing method expects a different object type for its signing keys. See the package documentation for details. Here are the most common ones:
|
Each signing method expects a different object type for its signing keys. See the package documentation for details. Here are the most common ones:
|
||||||
|
|
||||||
* The [HMAC signing method](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#SigningMethodHMAC) (`HS256`,`HS384`,`HS512`) expect `[]byte` values for signing and validation
|
* The [HMAC signing method](https://pkg.go.dev/git.internal/re/jwt/v4#SigningMethodHMAC) (`HS256`,`HS384`,`HS512`) expect `[]byte` values for signing and validation
|
||||||
* The [RSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#SigningMethodRSA) (`RS256`,`RS384`,`RS512`) expect `*rsa.PrivateKey` for signing and `*rsa.PublicKey` for validation
|
* The [RSA signing method](https://pkg.go.dev/git.internal/re/jwt/v4#SigningMethodRSA) (`RS256`,`RS384`,`RS512`) expect `*rsa.PrivateKey` for signing and `*rsa.PublicKey` for validation
|
||||||
* The [ECDSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#SigningMethodECDSA) (`ES256`,`ES384`,`ES512`) expect `*ecdsa.PrivateKey` for signing and `*ecdsa.PublicKey` for validation
|
* The [ECDSA signing method](https://pkg.go.dev/git.internal/re/jwt/v4#SigningMethodECDSA) (`ES256`,`ES384`,`ES512`) expect `*ecdsa.PrivateKey` for signing and `*ecdsa.PublicKey` for validation
|
||||||
* The [EdDSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#SigningMethodEd25519) (`Ed25519`) expect `ed25519.PrivateKey` for signing and `ed25519.PublicKey` for validation
|
* The [EdDSA signing method](https://pkg.go.dev/git.internal/re/jwt/v4#SigningMethodEd25519) (`Ed25519`) expect `ed25519.PrivateKey` for signing and `ed25519.PublicKey` for validation
|
||||||
|
|
||||||
### JWT and OAuth
|
### JWT and OAuth
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ This library uses descriptive error messages whenever possible. If you are not g
|
||||||
|
|
||||||
## More
|
## More
|
||||||
|
|
||||||
Documentation can be found [on pkg.go.dev](https://pkg.go.dev/github.com/golang-jwt/jwt/v4).
|
Documentation can be found [on pkg.go.dev](https://pkg.go.dev/git.internal/re/jwt/v4).
|
||||||
|
|
||||||
The command line utility included in this project (cmd/jwt) provides a straightforward example of token creation and parsing as well as a useful tool for debugging your own integration. You'll also find several implementation examples in the documentation.
|
The command line utility included in this project (cmd/jwt) provides a straightforward example of token creation and parsing as well as a useful tool for debugging your own integration. You'll also find several implementation examples in the documentation.
|
||||||
|
|
||||||
|
|
|
@ -265,9 +265,5 @@ func verifyIss(iss string, cmp string, required bool) bool {
|
||||||
if iss == "" {
|
if iss == "" {
|
||||||
return !required
|
return !required
|
||||||
}
|
}
|
||||||
if subtle.ConstantTimeCompare([]byte(iss), []byte(cmp)) != 0 {
|
return subtle.ConstantTimeCompare([]byte(iss), []byte(cmp)) != 0
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,4 +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/v4/cmd/jwt
|
go install git.internal/re/jwt/v4/cmd/jwt
|
|
@ -17,7 +17,7 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt/v4"
|
"git.internal/re/jwt/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt/v4"
|
"git.internal/re/jwt/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ecdsaTestData = []struct {
|
var ecdsaTestData = []struct {
|
||||||
|
@ -90,7 +90,6 @@ func TestECDSASign(t *testing.T) {
|
||||||
toSign := strings.Join(parts[0:2], ".")
|
toSign := strings.Join(parts[0:2], ".")
|
||||||
method := jwt.GetSigningMethod(data.alg)
|
method := jwt.GetSigningMethod(data.alg)
|
||||||
sig, err := method.Sign(toSign, ecdsaKey)
|
sig, err := method.Sign(toSign, ecdsaKey)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("[%v] Error signing token: %v", data.name, err)
|
t.Errorf("[%v] Error signing token: %v", data.name, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt/v4"
|
"git.internal/re/jwt/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ed25519TestData = []struct {
|
var ed25519TestData = []struct {
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt/v4"
|
"git.internal/re/jwt/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Example (atypical) using the RegisteredClaims type by itself to parse a token.
|
// Example (atypical) using the RegisteredClaims type by itself to parse a token.
|
||||||
|
@ -25,7 +25,7 @@ func ExampleNewWithClaims_registeredClaims() {
|
||||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||||
ss, err := token.SignedString(mySigningKey)
|
ss, err := token.SignedString(mySigningKey)
|
||||||
fmt.Printf("%v %v", ss, err)
|
fmt.Printf("%v %v", ss, err)
|
||||||
//Output: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ0ZXN0IiwiZXhwIjoxNTE2MjM5MDIyfQ.0XN_1Tpp9FszFOonIBpwha0c_SfnNI22DhTnjMshPg8 <nil>
|
// Output: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ0ZXN0IiwiZXhwIjoxNTE2MjM5MDIyfQ.0XN_1Tpp9FszFOonIBpwha0c_SfnNI22DhTnjMshPg8 <nil>
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example creating a token using a custom claims type. The RegisteredClaims is embedded
|
// Example creating a token using a custom claims type. The RegisteredClaims is embedded
|
||||||
|
@ -67,7 +67,7 @@ func ExampleNewWithClaims_customClaimsType() {
|
||||||
ss, err := token.SignedString(mySigningKey)
|
ss, err := token.SignedString(mySigningKey)
|
||||||
fmt.Printf("%v %v", ss, err)
|
fmt.Printf("%v %v", ss, err)
|
||||||
|
|
||||||
//Output: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJpc3MiOiJ0ZXN0IiwiZXhwIjoxNTE2MjM5MDIyfQ.xVuY2FZ_MRXMIEgVQ7J-TFtaucVFRXUzHm9LmV41goM <nil>
|
// Output: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJpc3MiOiJ0ZXN0IiwiZXhwIjoxNTE2MjM5MDIyfQ.xVuY2FZ_MRXMIEgVQ7J-TFtaucVFRXUzHm9LmV41goM <nil>
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example creating a token using a custom claims type. The StandardClaim is embedded
|
// Example creating a token using a custom claims type. The StandardClaim is embedded
|
||||||
|
@ -96,7 +96,7 @@ func ExampleParseWithClaims_customClaimsType() {
|
||||||
// An example of parsing the error types using bitfield checks
|
// An example of parsing the error types using bitfield checks
|
||||||
func ExampleParse_errorChecking() {
|
func ExampleParse_errorChecking() {
|
||||||
// Token from another example. This token is expired
|
// Token from another example. This token is expired
|
||||||
var tokenString = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJleHAiOjE1MDAwLCJpc3MiOiJ0ZXN0In0.HE7fK0xOQwFEr4WDgRWj4teRPZ6i3GLwD5YCm6Pwu_c"
|
tokenString := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJleHAiOjE1MDAwLCJpc3MiOiJ0ZXN0In0.HE7fK0xOQwFEr4WDgRWj4teRPZ6i3GLwD5YCm6Pwu_c"
|
||||||
|
|
||||||
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
||||||
return []byte("AllYourBase"), nil
|
return []byte("AllYourBase"), nil
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -1,4 +1,4 @@
|
||||||
module github.com/golang-jwt/jwt/v4
|
module git.internal/re/jwt/v4
|
||||||
|
|
||||||
go 1.16
|
go 1.16
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt/v4"
|
"git.internal/re/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/v4"
|
"git.internal/re/jwt/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
var hmacTestData = []struct {
|
var hmacTestData = []struct {
|
||||||
|
|
|
@ -16,8 +16,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt/v4"
|
"git.internal/re/jwt/v4"
|
||||||
"github.com/golang-jwt/jwt/v4/request"
|
"git.internal/re/jwt/v4/request"
|
||||||
)
|
)
|
||||||
|
|
||||||
// location of the files used for signing and verification
|
// location of the files used for signing and verification
|
||||||
|
@ -73,7 +73,7 @@ type CustomerInfo struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type CustomClaimsExample struct {
|
type CustomClaimsExample struct {
|
||||||
*jwt.RegisteredClaims
|
jwt.RegisteredClaims
|
||||||
TokenType string
|
TokenType string
|
||||||
CustomerInfo
|
CustomerInfo
|
||||||
}
|
}
|
||||||
|
@ -109,11 +109,10 @@ func Example_getTokenViaHTTP() {
|
||||||
claims := token.Claims.(*CustomClaimsExample)
|
claims := token.Claims.(*CustomClaimsExample)
|
||||||
fmt.Println(claims.CustomerInfo.Name)
|
fmt.Println(claims.CustomerInfo.Name)
|
||||||
|
|
||||||
//Output: test
|
// Output: test
|
||||||
}
|
}
|
||||||
|
|
||||||
func Example_useTokenViaHTTP() {
|
func Example_useTokenViaHTTP() {
|
||||||
|
|
||||||
// Make a sample token
|
// Make a sample token
|
||||||
// In a real world situation, this token will have been acquired from
|
// In a real world situation, this token will have been acquired from
|
||||||
// some other API call (see Example_getTokenViaHTTP)
|
// some other API call (see Example_getTokenViaHTTP)
|
||||||
|
@ -142,7 +141,7 @@ func createToken(user string) (string, error) {
|
||||||
|
|
||||||
// set our claims
|
// set our claims
|
||||||
t.Claims = &CustomClaimsExample{
|
t.Claims = &CustomClaimsExample{
|
||||||
&jwt.RegisteredClaims{
|
jwt.RegisteredClaims{
|
||||||
// set the expire time
|
// set the expire time
|
||||||
// see https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4
|
// see https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4
|
||||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Minute * 1)),
|
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Minute * 1)),
|
||||||
|
@ -197,7 +196,6 @@ func restrictedHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
// 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{}))
|
}, 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 {
|
||||||
w.WriteHeader(http.StatusUnauthorized)
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt/v4"
|
"git.internal/re/jwt/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
var noneTestData = []struct {
|
var noneTestData = []struct {
|
||||||
|
|
|
@ -42,6 +42,13 @@ func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) {
|
||||||
return p.ParseWithClaims(tokenString, MapClaims{}, keyFunc)
|
return p.ParseWithClaims(tokenString, MapClaims{}, keyFunc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseWithClaims parses, validates, and verifies like Parse, but supplies a default object implementing the Claims
|
||||||
|
// interface. This provides default values which can be overridden and allows a caller to use their own type, rather
|
||||||
|
// than the default MapClaims implementation of Claims.
|
||||||
|
//
|
||||||
|
// Note: If you provide a custom claim implementation that embeds one of the standard claims (such as RegisteredClaims),
|
||||||
|
// make sure that a) you either embed a non-pointer version of the claims or b) if you are using a pointer, allocate the
|
||||||
|
// proper memory for it before passing in the overall claims, otherwise you might run into a panic.
|
||||||
func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) {
|
func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) {
|
||||||
token, parts, err := p.ParseUnverified(tokenString, claims)
|
token, parts, err := p.ParseUnverified(tokenString, claims)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
116
parser_test.go
116
parser_test.go
|
@ -10,8 +10,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt/v4"
|
"git.internal/re/jwt/v4"
|
||||||
"github.com/golang-jwt/jwt/v4/test"
|
"git.internal/re/jwt/v4/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
var errKeyFuncError error = fmt.Errorf("error loading key")
|
var errKeyFuncError error = fmt.Errorf("error loading key")
|
||||||
|
@ -42,7 +42,6 @@ func init() {
|
||||||
// Load private keys
|
// Load private keys
|
||||||
jwtTestRSAPrivateKey = test.LoadRSAPrivateKeyFromDisk("test/sample_key")
|
jwtTestRSAPrivateKey = test.LoadRSAPrivateKeyFromDisk("test/sample_key")
|
||||||
jwtTestEC256PrivateKey = test.LoadECPrivateKeyFromDisk("test/ec256-private.pem")
|
jwtTestEC256PrivateKey = test.LoadECPrivateKeyFromDisk("test/ec256-private.pem")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var jwtTestData = []struct {
|
var jwtTestData = []struct {
|
||||||
|
@ -338,11 +337,9 @@ func signToken(claims jwt.Claims, signingMethod jwt.SigningMethod) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParser_Parse(t *testing.T) {
|
func TestParser_Parse(t *testing.T) {
|
||||||
|
|
||||||
// Iterate over test data set and run tests
|
// Iterate over test data set and run tests
|
||||||
for _, data := range jwtTestData {
|
for _, data := range jwtTestData {
|
||||||
t.Run(data.name, func(t *testing.T) {
|
t.Run(data.name, func(t *testing.T) {
|
||||||
|
|
||||||
// If the token string is blank, use helper function to generate string
|
// If the token string is blank, use helper function to generate string
|
||||||
if data.tokenString == "" {
|
if data.tokenString == "" {
|
||||||
data.tokenString = signToken(data.claims, data.signingMethod)
|
data.tokenString = signToken(data.claims, data.signingMethod)
|
||||||
|
@ -352,7 +349,7 @@ func TestParser_Parse(t *testing.T) {
|
||||||
var token *jwt.Token
|
var token *jwt.Token
|
||||||
var ve *jwt.ValidationError
|
var ve *jwt.ValidationError
|
||||||
var err error
|
var err error
|
||||||
var parser = data.parser
|
parser := data.parser
|
||||||
if parser == nil {
|
if parser == nil {
|
||||||
parser = new(jwt.Parser)
|
parser = new(jwt.Parser)
|
||||||
}
|
}
|
||||||
|
@ -404,7 +401,7 @@ func TestParser_Parse(t *testing.T) {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("[%v] Expecting error(s). Didn't get one.", data.name)
|
t.Errorf("[%v] Expecting error(s). Didn't get one.", data.name)
|
||||||
} else {
|
} else {
|
||||||
var all = false
|
all := false
|
||||||
for _, e := range data.err {
|
for _, e := range data.err {
|
||||||
all = errors.Is(err, e)
|
all = errors.Is(err, e)
|
||||||
}
|
}
|
||||||
|
@ -429,7 +426,6 @@ func TestParser_Parse(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParser_ParseUnverified(t *testing.T) {
|
func TestParser_ParseUnverified(t *testing.T) {
|
||||||
|
|
||||||
// Iterate over test data set and run tests
|
// Iterate over test data set and run tests
|
||||||
for _, data := range jwtTestData {
|
for _, data := range jwtTestData {
|
||||||
// Skip test data, that intentionally contains malformed tokens, as they would lead to an error
|
// Skip test data, that intentionally contains malformed tokens, as they would lead to an error
|
||||||
|
@ -446,7 +442,7 @@ func TestParser_ParseUnverified(t *testing.T) {
|
||||||
// Parse the token
|
// Parse the token
|
||||||
var token *jwt.Token
|
var token *jwt.Token
|
||||||
var err error
|
var err error
|
||||||
var parser = data.parser
|
parser := data.parser
|
||||||
if parser == nil {
|
if parser == nil {
|
||||||
parser = new(jwt.Parser)
|
parser = new(jwt.Parser)
|
||||||
}
|
}
|
||||||
|
@ -489,6 +485,7 @@ var setPaddingTestData = []struct {
|
||||||
tokenString string
|
tokenString string
|
||||||
claims jwt.Claims
|
claims jwt.Claims
|
||||||
paddedDecode bool
|
paddedDecode bool
|
||||||
|
strictDecode bool
|
||||||
signingMethod jwt.SigningMethod
|
signingMethod jwt.SigningMethod
|
||||||
keyfunc jwt.Keyfunc
|
keyfunc jwt.Keyfunc
|
||||||
valid bool
|
valid bool
|
||||||
|
@ -547,19 +544,108 @@ var setPaddingTestData = []struct {
|
||||||
keyfunc: paddedKeyFunc,
|
keyfunc: paddedKeyFunc,
|
||||||
valid: true,
|
valid: true,
|
||||||
},
|
},
|
||||||
|
// DecodeStrict tests, DecodePaddingAllowed=false
|
||||||
|
{
|
||||||
|
name: "Validated non-padded token with padding disabled, non-strict decode, non-tweaked signature",
|
||||||
|
tokenString: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJwYWRkZWRiYXIifQ.bI15h-7mN0f-2diX5I4ErgNQy1uM-rJS5Sz7O0iTWtWSBxY1h6wy8Ywxe5EZTEO6GiIfk7Lk-72Ex-c5aA40QKhPwWB9BJ8O_LfKpezUVBOn0jRItDnVdsk4ccl2zsOVkbA4U4QvdrSbOYMbwoRHzDXfTFpoeMWtn3ez0aENJ8dh4E1echHp5ByI9Pu2aBsvM1WVcMt_BySweCL3f4T7jNZeXDr7Txd00yUd2gdsHYPjXorOvsgaBKN5GLsWd1zIY5z-2gCC8CRSN-IJ4NNX5ifh7l-bOXE2q7szTqa9pvyE9y6TQJhNMSE2FotRce_TOPBWgGpQ-K2I7E8x7wZ8O" +
|
||||||
|
"g",
|
||||||
|
claims: nil,
|
||||||
|
paddedDecode: false,
|
||||||
|
strictDecode: false,
|
||||||
|
signingMethod: jwt.SigningMethodRS256,
|
||||||
|
keyfunc: defaultKeyFunc,
|
||||||
|
valid: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Validated non-padded token with padding disabled, non-strict decode, tweaked signature",
|
||||||
|
tokenString: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJwYWRkZWRiYXIifQ.bI15h-7mN0f-2diX5I4ErgNQy1uM-rJS5Sz7O0iTWtWSBxY1h6wy8Ywxe5EZTEO6GiIfk7Lk-72Ex-c5aA40QKhPwWB9BJ8O_LfKpezUVBOn0jRItDnVdsk4ccl2zsOVkbA4U4QvdrSbOYMbwoRHzDXfTFpoeMWtn3ez0aENJ8dh4E1echHp5ByI9Pu2aBsvM1WVcMt_BySweCL3f4T7jNZeXDr7Txd00yUd2gdsHYPjXorOvsgaBKN5GLsWd1zIY5z-2gCC8CRSN-IJ4NNX5ifh7l-bOXE2q7szTqa9pvyE9y6TQJhNMSE2FotRce_TOPBWgGpQ-K2I7E8x7wZ8O" +
|
||||||
|
"h",
|
||||||
|
claims: nil,
|
||||||
|
paddedDecode: false,
|
||||||
|
strictDecode: false,
|
||||||
|
signingMethod: jwt.SigningMethodRS256,
|
||||||
|
keyfunc: defaultKeyFunc,
|
||||||
|
valid: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Validated non-padded token with padding disabled, strict decode, non-tweaked signature",
|
||||||
|
tokenString: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJwYWRkZWRiYXIifQ.bI15h-7mN0f-2diX5I4ErgNQy1uM-rJS5Sz7O0iTWtWSBxY1h6wy8Ywxe5EZTEO6GiIfk7Lk-72Ex-c5aA40QKhPwWB9BJ8O_LfKpezUVBOn0jRItDnVdsk4ccl2zsOVkbA4U4QvdrSbOYMbwoRHzDXfTFpoeMWtn3ez0aENJ8dh4E1echHp5ByI9Pu2aBsvM1WVcMt_BySweCL3f4T7jNZeXDr7Txd00yUd2gdsHYPjXorOvsgaBKN5GLsWd1zIY5z-2gCC8CRSN-IJ4NNX5ifh7l-bOXE2q7szTqa9pvyE9y6TQJhNMSE2FotRce_TOPBWgGpQ-K2I7E8x7wZ8O" +
|
||||||
|
"g",
|
||||||
|
claims: nil,
|
||||||
|
paddedDecode: false,
|
||||||
|
strictDecode: true,
|
||||||
|
signingMethod: jwt.SigningMethodRS256,
|
||||||
|
keyfunc: defaultKeyFunc,
|
||||||
|
valid: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Error for non-padded token with padding disabled, strict decode, tweaked signature",
|
||||||
|
tokenString: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJwYWRkZWRiYXIifQ.bI15h-7mN0f-2diX5I4ErgNQy1uM-rJS5Sz7O0iTWtWSBxY1h6wy8Ywxe5EZTEO6GiIfk7Lk-72Ex-c5aA40QKhPwWB9BJ8O_LfKpezUVBOn0jRItDnVdsk4ccl2zsOVkbA4U4QvdrSbOYMbwoRHzDXfTFpoeMWtn3ez0aENJ8dh4E1echHp5ByI9Pu2aBsvM1WVcMt_BySweCL3f4T7jNZeXDr7Txd00yUd2gdsHYPjXorOvsgaBKN5GLsWd1zIY5z-2gCC8CRSN-IJ4NNX5ifh7l-bOXE2q7szTqa9pvyE9y6TQJhNMSE2FotRce_TOPBWgGpQ-K2I7E8x7wZ8O" +
|
||||||
|
"h",
|
||||||
|
claims: nil,
|
||||||
|
paddedDecode: false,
|
||||||
|
strictDecode: true,
|
||||||
|
signingMethod: jwt.SigningMethodRS256,
|
||||||
|
keyfunc: defaultKeyFunc,
|
||||||
|
valid: false,
|
||||||
|
},
|
||||||
|
// DecodeStrict tests, DecodePaddingAllowed=true
|
||||||
|
{
|
||||||
|
name: "Validated padded token with padding enabled, non-strict decode, non-tweaked signature",
|
||||||
|
tokenString: "eyJ0eXAiOiJKV1QiLCJraWQiOiIxMjM0NTY3OC1hYmNkLTEyMzQtYWJjZC0xMjM0NTY3OGFiY2QiLCJhbGciOiJFUzI1NiIsImlzcyI6Imh0dHBzOi8vY29nbml0by1pZHAuZXUtd2VzdC0yLmFtYXpvbmF3cy5jb20vIiwiY2xpZW50IjoiN0xUY29QWnJWNDR6ZVg2WUs5VktBcHZPM3EiLCJzaWduZXIiOiJhcm46YXdzOmVsYXN0aWNsb2FkYmFsYW5jaW5nIiwiZXhwIjoxNjI5NDcwMTAxfQ==.eyJzdWIiOiIxMjM0NTY3OC1hYmNkLTEyMzQtYWJjZC0xMjM0NTY3OGFiY2QiLCJlbWFpbF92ZXJpZmllZCI6InRydWUiLCJlbWFpbCI6InVzZXJAZXhhbXBsZS5jb20iLCJ1c2VybmFtZSI6IjEyMzQ1Njc4LWFiY2QtMTIzNC1hYmNkLTEyMzQ1Njc4YWJjZCIsImV4cCI6MTYyOTQ3MDEwMSwiaXNzIjoiaHR0cHM6Ly9jb2duaXRvLWlkcC5ldS13ZXN0LTIuYW1hem9uYXdzLmNvbS8ifQ==.sx0muJ754glJvwWgkHaPrOI3L1gaPjRLLUvOQRk0WitnqC5Dtt1knorcbOzlEcH9zwPM2jYYIAYQz_qEyM3gr" +
|
||||||
|
"w==",
|
||||||
|
claims: nil,
|
||||||
|
paddedDecode: true,
|
||||||
|
strictDecode: false,
|
||||||
|
signingMethod: jwt.SigningMethodES256,
|
||||||
|
keyfunc: paddedKeyFunc,
|
||||||
|
valid: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Validated padded token with padding enabled, non-strict decode, tweaked signature",
|
||||||
|
tokenString: "eyJ0eXAiOiJKV1QiLCJraWQiOiIxMjM0NTY3OC1hYmNkLTEyMzQtYWJjZC0xMjM0NTY3OGFiY2QiLCJhbGciOiJFUzI1NiIsImlzcyI6Imh0dHBzOi8vY29nbml0by1pZHAuZXUtd2VzdC0yLmFtYXpvbmF3cy5jb20vIiwiY2xpZW50IjoiN0xUY29QWnJWNDR6ZVg2WUs5VktBcHZPM3EiLCJzaWduZXIiOiJhcm46YXdzOmVsYXN0aWNsb2FkYmFsYW5jaW5nIiwiZXhwIjoxNjI5NDcwMTAxfQ==.eyJzdWIiOiIxMjM0NTY3OC1hYmNkLTEyMzQtYWJjZC0xMjM0NTY3OGFiY2QiLCJlbWFpbF92ZXJpZmllZCI6InRydWUiLCJlbWFpbCI6InVzZXJAZXhhbXBsZS5jb20iLCJ1c2VybmFtZSI6IjEyMzQ1Njc4LWFiY2QtMTIzNC1hYmNkLTEyMzQ1Njc4YWJjZCIsImV4cCI6MTYyOTQ3MDEwMSwiaXNzIjoiaHR0cHM6Ly9jb2duaXRvLWlkcC5ldS13ZXN0LTIuYW1hem9uYXdzLmNvbS8ifQ==.sx0muJ754glJvwWgkHaPrOI3L1gaPjRLLUvOQRk0WitnqC5Dtt1knorcbOzlEcH9zwPM2jYYIAYQz_qEyM3gr" +
|
||||||
|
"x==",
|
||||||
|
claims: nil,
|
||||||
|
paddedDecode: true,
|
||||||
|
strictDecode: false,
|
||||||
|
signingMethod: jwt.SigningMethodES256,
|
||||||
|
keyfunc: paddedKeyFunc,
|
||||||
|
valid: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Validated padded token with padding enabled, strict decode, non-tweaked signature",
|
||||||
|
tokenString: "eyJ0eXAiOiJKV1QiLCJraWQiOiIxMjM0NTY3OC1hYmNkLTEyMzQtYWJjZC0xMjM0NTY3OGFiY2QiLCJhbGciOiJFUzI1NiIsImlzcyI6Imh0dHBzOi8vY29nbml0by1pZHAuZXUtd2VzdC0yLmFtYXpvbmF3cy5jb20vIiwiY2xpZW50IjoiN0xUY29QWnJWNDR6ZVg2WUs5VktBcHZPM3EiLCJzaWduZXIiOiJhcm46YXdzOmVsYXN0aWNsb2FkYmFsYW5jaW5nIiwiZXhwIjoxNjI5NDcwMTAxfQ==.eyJzdWIiOiIxMjM0NTY3OC1hYmNkLTEyMzQtYWJjZC0xMjM0NTY3OGFiY2QiLCJlbWFpbF92ZXJpZmllZCI6InRydWUiLCJlbWFpbCI6InVzZXJAZXhhbXBsZS5jb20iLCJ1c2VybmFtZSI6IjEyMzQ1Njc4LWFiY2QtMTIzNC1hYmNkLTEyMzQ1Njc4YWJjZCIsImV4cCI6MTYyOTQ3MDEwMSwiaXNzIjoiaHR0cHM6Ly9jb2duaXRvLWlkcC5ldS13ZXN0LTIuYW1hem9uYXdzLmNvbS8ifQ==.sx0muJ754glJvwWgkHaPrOI3L1gaPjRLLUvOQRk0WitnqC5Dtt1knorcbOzlEcH9zwPM2jYYIAYQz_qEyM3gr" +
|
||||||
|
"w==",
|
||||||
|
claims: nil,
|
||||||
|
paddedDecode: true,
|
||||||
|
strictDecode: true,
|
||||||
|
signingMethod: jwt.SigningMethodES256,
|
||||||
|
keyfunc: paddedKeyFunc,
|
||||||
|
valid: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Error for padded token with padding enabled, strict decode, tweaked signature",
|
||||||
|
tokenString: "eyJ0eXAiOiJKV1QiLCJraWQiOiIxMjM0NTY3OC1hYmNkLTEyMzQtYWJjZC0xMjM0NTY3OGFiY2QiLCJhbGciOiJFUzI1NiIsImlzcyI6Imh0dHBzOi8vY29nbml0by1pZHAuZXUtd2VzdC0yLmFtYXpvbmF3cy5jb20vIiwiY2xpZW50IjoiN0xUY29QWnJWNDR6ZVg2WUs5VktBcHZPM3EiLCJzaWduZXIiOiJhcm46YXdzOmVsYXN0aWNsb2FkYmFsYW5jaW5nIiwiZXhwIjoxNjI5NDcwMTAxfQ==.eyJzdWIiOiIxMjM0NTY3OC1hYmNkLTEyMzQtYWJjZC0xMjM0NTY3OGFiY2QiLCJlbWFpbF92ZXJpZmllZCI6InRydWUiLCJlbWFpbCI6InVzZXJAZXhhbXBsZS5jb20iLCJ1c2VybmFtZSI6IjEyMzQ1Njc4LWFiY2QtMTIzNC1hYmNkLTEyMzQ1Njc4YWJjZCIsImV4cCI6MTYyOTQ3MDEwMSwiaXNzIjoiaHR0cHM6Ly9jb2duaXRvLWlkcC5ldS13ZXN0LTIuYW1hem9uYXdzLmNvbS8ifQ==.sx0muJ754glJvwWgkHaPrOI3L1gaPjRLLUvOQRk0WitnqC5Dtt1knorcbOzlEcH9zwPM2jYYIAYQz_qEyM3gr" +
|
||||||
|
"x==",
|
||||||
|
claims: nil,
|
||||||
|
paddedDecode: true,
|
||||||
|
strictDecode: true,
|
||||||
|
signingMethod: jwt.SigningMethodES256,
|
||||||
|
keyfunc: paddedKeyFunc,
|
||||||
|
valid: false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extension of Parsing, this is to test out functionality specific to switching codecs with padding.
|
// Extension of Parsing, this is to test out functionality specific to switching codecs with padding.
|
||||||
func TestSetPadding(t *testing.T) {
|
func TestSetPadding(t *testing.T) {
|
||||||
for _, data := range setPaddingTestData {
|
for _, data := range setPaddingTestData {
|
||||||
t.Run(data.name, func(t *testing.T) {
|
t.Run(data.name, func(t *testing.T) {
|
||||||
|
jwt.DecodePaddingAllowed = data.paddedDecode
|
||||||
|
jwt.DecodeStrict = data.strictDecode
|
||||||
|
|
||||||
// If the token string is blank, use helper function to generate string
|
// If the token string is blank, use helper function to generate string
|
||||||
jwt.DecodePaddingAllowed = data.paddedDecode
|
|
||||||
|
|
||||||
if data.tokenString == "" {
|
if data.tokenString == "" {
|
||||||
data.tokenString = signToken(data.claims, data.signingMethod)
|
data.tokenString = signToken(data.claims, data.signingMethod)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the token
|
// Parse the token
|
||||||
|
@ -578,15 +664,13 @@ func TestSetPadding(t *testing.T) {
|
||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
jwt.DecodePaddingAllowed = false
|
jwt.DecodePaddingAllowed = false
|
||||||
|
jwt.DecodeStrict = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkParseUnverified(b *testing.B) {
|
func BenchmarkParseUnverified(b *testing.B) {
|
||||||
|
|
||||||
// Iterate over test data set and run tests
|
// Iterate over test data set and run tests
|
||||||
for _, data := range jwtTestData {
|
for _, data := range jwtTestData {
|
||||||
// If the token string is blank, use helper function to generate string
|
// If the token string is blank, use helper function to generate string
|
||||||
|
@ -595,7 +679,7 @@ func BenchmarkParseUnverified(b *testing.B) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the token
|
// Parse the token
|
||||||
var parser = data.parser
|
parser := data.parser
|
||||||
if parser == nil {
|
if parser == nil {
|
||||||
parser = new(jwt.Parser)
|
parser = new(jwt.Parser)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ package request
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt/v4"
|
"git.internal/re/jwt/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ParseFromRequest extracts and parses a JWT token from an HTTP request.
|
// ParseFromRequest extracts and parses a JWT token from an HTTP request.
|
||||||
|
|
|
@ -8,8 +8,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt/v4"
|
"git.internal/re/jwt/v4"
|
||||||
"github.com/golang-jwt/jwt/v4/test"
|
"git.internal/re/jwt/v4/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
var requestTestData = []struct {
|
var requestTestData = []struct {
|
||||||
|
|
|
@ -10,8 +10,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt/v4"
|
"git.internal/re/jwt/v4"
|
||||||
"github.com/golang-jwt/jwt/v4/test"
|
"git.internal/re/jwt/v4/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
var rsaPSSTestData = []struct {
|
var rsaPSSTestData = []struct {
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt/v4"
|
"git.internal/re/jwt/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
var rsaTestData = []struct {
|
var rsaTestData = []struct {
|
||||||
|
@ -147,7 +147,6 @@ func TestRSAKeyParsing(t *testing.T) {
|
||||||
if k, e := jwt.ParseRSAPublicKeyFromPEM(badKey); e == nil {
|
if k, e := jwt.ParseRSAPublicKeyFromPEM(badKey); e == nil {
|
||||||
t.Errorf("Parsed invalid key as valid private key: %v", k)
|
t.Errorf("Parsed invalid key as valid private key: %v", k)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkRSAParsing(b *testing.B) {
|
func BenchmarkRSAParsing(b *testing.B) {
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt/v4"
|
"git.internal/re/jwt/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
func LoadRSAPrivateKeyFromDisk(location string) *rsa.PrivateKey {
|
func LoadRSAPrivateKeyFromDisk(location string) *rsa.PrivateKey {
|
||||||
|
|
20
token.go
20
token.go
|
@ -14,6 +14,12 @@ import (
|
||||||
// To use the non-recommended decoding, set this boolean to `true` prior to using this package.
|
// To use the non-recommended decoding, set this boolean to `true` prior to using this package.
|
||||||
var DecodePaddingAllowed bool
|
var DecodePaddingAllowed bool
|
||||||
|
|
||||||
|
// DecodeStrict will switch the codec used for decoding JWTs into strict mode.
|
||||||
|
// In this mode, the decoder requires that trailing padding bits are zero, as described in RFC 4648 section 3.5.
|
||||||
|
// Note that this is a global variable, and updating it will change the behavior on a package level, and is also NOT go-routine safe.
|
||||||
|
// To use strict decoding, set this boolean to `true` prior to using this package.
|
||||||
|
var DecodeStrict bool
|
||||||
|
|
||||||
// TimeFunc provides the current time when parsing token to validate "exp" claim (expiration time).
|
// TimeFunc provides the current time when parsing token to validate "exp" claim (expiration time).
|
||||||
// You can override it to use another time value. This is useful for testing or if your
|
// You can override it to use another time value. This is useful for testing or if your
|
||||||
// server uses a different time zone than your tokens.
|
// server uses a different time zone than your tokens.
|
||||||
|
@ -99,6 +105,11 @@ func Parse(tokenString string, keyFunc Keyfunc, options ...ParserOption) (*Token
|
||||||
return NewParser(options...).Parse(tokenString, keyFunc)
|
return NewParser(options...).Parse(tokenString, keyFunc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseWithClaims is a shortcut for NewParser().ParseWithClaims().
|
||||||
|
//
|
||||||
|
// Note: If you provide a custom claim implementation that embeds one of the standard claims (such as RegisteredClaims),
|
||||||
|
// make sure that a) you either embed a non-pointer version of the claims or b) if you are using a pointer, allocate the
|
||||||
|
// proper memory for it before passing in the overall claims, otherwise you might run into a panic.
|
||||||
func ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc, options ...ParserOption) (*Token, error) {
|
func ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc, options ...ParserOption) (*Token, error) {
|
||||||
return NewParser(options...).ParseWithClaims(tokenString, claims, keyFunc)
|
return NewParser(options...).ParseWithClaims(tokenString, claims, keyFunc)
|
||||||
}
|
}
|
||||||
|
@ -116,12 +127,17 @@ func EncodeSegment(seg []byte) string {
|
||||||
// Deprecated: In a future release, we will demote this function to a non-exported function, since it
|
// Deprecated: In a future release, we will demote this function to a non-exported function, since it
|
||||||
// should only be used internally
|
// should only be used internally
|
||||||
func DecodeSegment(seg string) ([]byte, error) {
|
func DecodeSegment(seg string) ([]byte, error) {
|
||||||
|
encoding := base64.RawURLEncoding
|
||||||
|
|
||||||
if DecodePaddingAllowed {
|
if DecodePaddingAllowed {
|
||||||
if l := len(seg) % 4; l > 0 {
|
if l := len(seg) % 4; l > 0 {
|
||||||
seg += strings.Repeat("=", 4-l)
|
seg += strings.Repeat("=", 4-l)
|
||||||
}
|
}
|
||||||
return base64.URLEncoding.DecodeString(seg)
|
encoding = base64.URLEncoding
|
||||||
}
|
}
|
||||||
|
|
||||||
return base64.RawURLEncoding.DecodeString(seg)
|
if DecodeStrict {
|
||||||
|
encoding = encoding.Strict()
|
||||||
|
}
|
||||||
|
return encoding.DecodeString(seg)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ package jwt_test
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt/v4"
|
"git.internal/re/jwt/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestToken_SigningString(t1 *testing.T) {
|
func TestToken_SigningString(t1 *testing.T) {
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt/v4"
|
"git.internal/re/jwt/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNumericDate(t *testing.T) {
|
func TestNumericDate(t *testing.T) {
|
||||||
|
@ -41,7 +41,6 @@ func TestSingleArrayMarshal(t *testing.T) {
|
||||||
expected := `"test"`
|
expected := `"test"`
|
||||||
|
|
||||||
b, err := json.Marshal(s)
|
b, err := json.Marshal(s)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Unexpected error: %s", err)
|
t.Errorf("Unexpected error: %s", err)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue