Skip to content

Commit 20b02ba

Browse files
committed
feat: add backward-compat alias types
1 parent b3d339a commit 20b02ba

10 files changed

+51
-39
lines changed

cmd/jwt/main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ func verifyToken() error {
128128
}
129129

130130
// Parse the token. Load the key from command line option
131-
token, err := jwt.Parse(string(tokData), func(t *jwt.Token[jwt.MapClaims]) (interface{}, error) {
131+
token, err := jwt.Parse(string(tokData), func(t *jwt.TokenFor[jwt.MapClaims]) (interface{}, error) {
132132
if isNone() {
133133
return jwt.UnsafeAllowNoneSignatureType, nil
134134
}

example_test.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ func ExampleParseWithClaims_customClaimsType() {
8080
jwt.RegisteredClaims
8181
}
8282

83-
token, err := jwt.ParseWithClaims(tokenString, func(token *jwt.Token[*MyCustomClaims]) (interface{}, error) {
83+
token, err := jwt.ParseWithClaims(tokenString, func(token *jwt.TokenFor[*MyCustomClaims]) (interface{}, error) {
8484
return []byte("AllYourBase"), nil
8585
})
8686

@@ -103,7 +103,7 @@ func ExampleParseWithClaims_validationOptions() {
103103
jwt.RegisteredClaims
104104
}
105105

106-
token, err := jwt.ParseWithClaims(tokenString, func(token *jwt.Token[*MyCustomClaims]) (interface{}, error) {
106+
token, err := jwt.ParseWithClaims(tokenString, func(token *jwt.TokenFor[*MyCustomClaims]) (interface{}, error) {
107107
return []byte("AllYourBase"), nil
108108
}, jwt.WithLeeway(5*time.Second))
109109

@@ -136,7 +136,7 @@ func (m MyCustomClaims) CustomValidation() error {
136136
func ExampleParseWithClaims_customValidation() {
137137
tokenString := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJpc3MiOiJ0ZXN0IiwiYXVkIjoic2luZ2xlIn0.QAWg1vGvnqRuCFTMcPkjZljXHh8U3L_qUjszOtQbeaA"
138138

139-
token, err := jwt.ParseWithClaims(tokenString, func(token *jwt.Token[*MyCustomClaims]) (interface{}, error) {
139+
token, err := jwt.ParseWithClaims(tokenString, func(token *jwt.TokenFor[*MyCustomClaims]) (interface{}, error) {
140140
return []byte("AllYourBase"), nil
141141
}, jwt.WithLeeway(5*time.Second))
142142

@@ -154,7 +154,7 @@ func ExampleParse_errorChecking() {
154154
// Token from another example. This token is expired
155155
tokenString := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJleHAiOjE1MDAwLCJpc3MiOiJ0ZXN0In0.HE7fK0xOQwFEr4WDgRWj4teRPZ6i3GLwD5YCm6Pwu_c"
156156

157-
token, err := jwt.Parse(tokenString, func(token *jwt.Token[jwt.MapClaims]) (interface{}, error) {
157+
token, err := jwt.Parse(tokenString, func(token *jwt.TokenFor[jwt.MapClaims]) (interface{}, error) {
158158
return []byte("AllYourBase"), nil
159159
})
160160

hmac_example_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ func ExampleParse_hmac() {
4747
// useful if you use multiple keys for your application. The standard is to use 'kid' in the
4848
// head of the token to identify which key to use, but the parsed token (head and claims) is provided
4949
// to the callback, providing flexibility.
50-
token, err := jwt.Parse(tokenString, func(token *jwt.Token[jwt.MapClaims]) (interface{}, error) {
50+
token, err := jwt.Parse(tokenString, func(token *jwt.TokenFor[jwt.MapClaims]) (interface{}, error) {
5151
// Don't forget to validate the alg is what you expect:
5252
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
5353
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])

http_example_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ func Example_getTokenViaHTTP() {
9999
tokenString := strings.TrimSpace(buf.String())
100100

101101
// Parse the token
102-
token, err := jwt.ParseWithClaims(tokenString, func(token *jwt.Token[*CustomClaimsExample]) (interface{}, error) {
102+
token, err := jwt.ParseWithClaims(tokenString, func(token *jwt.TokenFor[*CustomClaimsExample]) (interface{}, error) {
103103
// since we only use the one private key to sign the tokens,
104104
// we also only use its public counter part to verify
105105
return verifyKey, nil
@@ -191,7 +191,7 @@ func authHandler(w http.ResponseWriter, r *http.Request) {
191191
// only accessible with a valid token
192192
func restrictedHandler(w http.ResponseWriter, r *http.Request) {
193193
// Get token from request
194-
token, err := request.ParseFromRequest(r, request.OAuth2Extractor, func(token *jwt.Token[*CustomClaimsExample]) (interface{}, error) {
194+
token, err := request.ParseFromRequestWithClaims(r, request.OAuth2Extractor, func(token *jwt.TokenFor[*CustomClaimsExample]) (interface{}, error) {
195195
// since we only use the one private key to sign the tokens,
196196
// we also only use its public counter part to verify
197197
return verifyKey, nil

parser.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ func NewParserFor[T Claims](options ...ParserOption) *Parser[T] {
5757
// Note: If you provide a custom claim implementation that embeds one of the standard claims (such as RegisteredClaims),
5858
// make sure that a) you either embed a non-pointer version of the claims or b) if you are using a pointer, allocate the
5959
// proper memory for it before passing in the overall claims, otherwise you might run into a panic.
60-
func (p *Parser[T]) Parse(tokenString string, keyFunc Keyfunc[T]) (*Token[T], error) {
60+
func (p *Parser[T]) Parse(tokenString string, keyFunc KeyfuncFor[T]) (*TokenFor[T], error) {
6161
token, parts, err := p.ParseUnverified(tokenString)
6262
if err != nil {
6363
return token, err
@@ -134,13 +134,13 @@ func (p *Parser[T]) Parse(tokenString string, keyFunc Keyfunc[T]) (*Token[T], er
134134
//
135135
// It's only ever useful in cases where you know the signature is valid (because it has
136136
// been checked previously in the stack) and you want to extract values from it.
137-
func (p *Parser[T]) ParseUnverified(tokenString string) (token *Token[T], parts []string, err error) {
137+
func (p *Parser[T]) ParseUnverified(tokenString string) (token *TokenFor[T], parts []string, err error) {
138138
parts = strings.Split(tokenString, ".")
139139
if len(parts) != 3 {
140140
return nil, parts, NewValidationError("token contains an invalid number of segments", ValidationErrorMalformed)
141141
}
142142

143-
token = &Token[T]{Raw: tokenString}
143+
token = &TokenFor[T]{Raw: tokenString}
144144

145145
// parse Header
146146
var headerBytes []byte

parser_test.go

+10-10
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,18 @@ const (
3535
keyFuncNil
3636
)
3737

38-
func getKeyFunc[T jwt.Claims](kind keyFuncKind) jwt.Keyfunc[T] {
38+
func getKeyFunc[T jwt.Claims](kind keyFuncKind) jwt.KeyfuncFor[T] {
3939
switch kind {
4040
case keyFuncDefault:
41-
return func(t *jwt.Token[T]) (interface{}, error) { return jwtTestDefaultKey, nil }
41+
return func(t *jwt.TokenFor[T]) (interface{}, error) { return jwtTestDefaultKey, nil }
4242
case keyFuncECDSA:
43-
return func(t *jwt.Token[T]) (interface{}, error) { return jwtTestEC256PublicKey, nil }
43+
return func(t *jwt.TokenFor[T]) (interface{}, error) { return jwtTestEC256PublicKey, nil }
4444
case keyFuncPadded:
45-
return func(t *jwt.Token[T]) (interface{}, error) { return paddedKey, nil }
45+
return func(t *jwt.TokenFor[T]) (interface{}, error) { return paddedKey, nil }
4646
case keyFuncEmpty:
47-
return func(t *jwt.Token[T]) (interface{}, error) { return nil, nil }
47+
return func(t *jwt.TokenFor[T]) (interface{}, error) { return nil, nil }
4848
case keyFuncError:
49-
return func(t *jwt.Token[T]) (interface{}, error) { return nil, errKeyFuncError }
49+
return func(t *jwt.TokenFor[T]) (interface{}, error) { return nil, errKeyFuncError }
5050
case keyFuncNil:
5151
return nil
5252
default:
@@ -371,8 +371,8 @@ func signToken(claims jwt.Claims, signingMethod jwt.SigningMethod) string {
371371

372372
// cloneToken is necesssary to "forget" the type information back to a generic jwt.Claims.
373373
// Assignment of parameterized types is currently (1.20) not supported.
374-
func cloneToken[T jwt.Claims](tin *jwt.Token[T]) *jwt.Token[jwt.Claims] {
375-
tout := &jwt.Token[jwt.Claims]{}
374+
func cloneToken[T jwt.Claims](tin *jwt.TokenFor[T]) *jwt.TokenFor[jwt.Claims] {
375+
tout := &jwt.TokenFor[jwt.Claims]{}
376376
tout.Claims = tin.Claims
377377
tout.Header = tin.Header
378378
tout.Method = tin.Method
@@ -392,7 +392,7 @@ func TestParser_Parse(t *testing.T) {
392392
}
393393

394394
// Parse the token
395-
var token *jwt.Token[jwt.Claims]
395+
var token *jwt.TokenFor[jwt.Claims]
396396
var err error
397397
var ve *jwt.ValidationError
398398
switch data.claims.(type) {
@@ -485,7 +485,7 @@ func TestParser_ParseUnverified(t *testing.T) {
485485
}
486486

487487
// Parse the token
488-
var token *jwt.Token[jwt.Claims]
488+
var token *jwt.TokenFor[jwt.Claims]
489489
var err error
490490
switch data.claims.(type) {
491491
case jwt.MapClaims:

request/request.go

+9-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@ import (
1212
// the logic for extracting a token. Several useful implementations are provided.
1313
//
1414
// You can provide options to modify parsing behavior
15-
func ParseFromRequest[T jwt.Claims](req *http.Request, extractor Extractor, keyFunc jwt.Keyfunc[T], options ...ParseFromRequestOption[T]) (token *jwt.Token[T], err error) {
15+
func ParseFromRequest(req *http.Request, extractor Extractor, keyFunc jwt.Keyfunc, options ...Option) (token *jwt.Token, err error) {
16+
return ParseFromRequestWithClaims(req, extractor, keyFunc, options...)
17+
}
18+
19+
func ParseFromRequestWithClaims[T jwt.Claims](req *http.Request, extractor Extractor, keyFunc jwt.KeyfuncFor[T], options ...OptionFor[T]) (token *jwt.TokenFor[T], err error) {
1620
// Create basic parser struct
1721
p := &fromRequestParser[T]{
1822
req: req,
@@ -45,10 +49,12 @@ type fromRequestParser[T jwt.Claims] struct {
4549
parser *jwt.Parser[T]
4650
}
4751

48-
type ParseFromRequestOption[T jwt.Claims] func(*fromRequestParser[T])
52+
type OptionFor[T jwt.Claims] func(*fromRequestParser[T])
53+
54+
type Option = OptionFor[jwt.MapClaims]
4955

5056
// WithParser parses using a custom parser
51-
func WithParser[T jwt.Claims](parser *jwt.Parser[T]) ParseFromRequestOption[T] {
57+
func WithParser[T jwt.Claims](parser *jwt.Parser[T]) OptionFor[T] {
5258
return func(p *fromRequestParser[T]) {
5359
p.parser = parser
5460
}

request/request_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ func TestParseRequest(t *testing.T) {
5858
// load keys from disk
5959
privateKey := test.LoadRSAPrivateKeyFromDisk("../test/sample_key")
6060
publicKey := test.LoadRSAPublicKeyFromDisk("../test/sample_key.pub")
61-
keyfunc := func(*jwt.Token[jwt.MapClaims]) (interface{}, error) {
61+
keyfunc := func(*jwt.TokenFor[jwt.MapClaims]) (interface{}, error) {
6262
return publicKey, nil
6363
}
6464

token.go

+18-12
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,18 @@ var DecodePaddingAllowed bool
1919
// To use strict decoding, set this boolean to `true` prior to using this package.
2020
var DecodeStrict bool
2121

22-
// Keyfunc will be used by the Parse methods as a callback function to supply
22+
// KeyfuncFor[T] will be used by the Parse methods as a callback function to supply
2323
// the key for verification. The function receives the parsed,
24-
// but unverified Token. This allows you to use properties in the
24+
// but unverified TokenFor[T]. This allows you to use properties in the
2525
// Header of the token (such as `kid`) to identify which key to use.
26-
type Keyfunc[T Claims] func(*Token[T]) (interface{}, error)
26+
type KeyfuncFor[T Claims] func(*TokenFor[T]) (interface{}, error)
2727

28-
// Token represents a JWT Token. Different fields will be used depending on whether you're
28+
// Keyfunc is an alias for KeyfuncFor[Claims], for backward compatibility.
29+
type Keyfunc = KeyfuncFor[MapClaims]
30+
31+
// TokenFor represents a JWT TokenFor. Different fields will be used depending on whether you're
2932
// creating or parsing/verifying a token.
30-
type Token[T Claims] struct {
33+
type TokenFor[T Claims] struct {
3134
Raw string // The raw token. Populated when you Parse a token
3235
Method SigningMethod // The signing method used or to be used
3336
Header map[string]interface{} // The first segment of the token
@@ -36,14 +39,17 @@ type Token[T Claims] struct {
3639
Valid bool // Is the token valid? Populated when you Parse/Verify a token
3740
}
3841

42+
// Token is an alias for TokenFor[Claims], for backward compatibility.
43+
type Token = TokenFor[MapClaims]
44+
3945
// New creates a new Token with the specified signing method and an empty map of claims.
40-
func New(method SigningMethod) *Token[MapClaims] {
46+
func New(method SigningMethod) *Token {
4147
return NewWithClaims(method, MapClaims{})
4248
}
4349

4450
// NewWithClaims creates a new Token with the specified signing method and claims.
45-
func NewWithClaims[T Claims](method SigningMethod, claims T) *Token[T] {
46-
return &Token[T]{
51+
func NewWithClaims[T Claims](method SigningMethod, claims T) *TokenFor[T] {
52+
return &TokenFor[T]{
4753
Header: map[string]interface{}{
4854
"typ": "JWT",
4955
"alg": method.Alg(),
@@ -55,7 +61,7 @@ func NewWithClaims[T Claims](method SigningMethod, claims T) *Token[T] {
5561

5662
// SignedString creates and returns a complete, signed JWT.
5763
// The token is signed using the SigningMethod specified in the token.
58-
func (t *Token[T]) SignedString(key interface{}) (string, error) {
64+
func (t *TokenFor[T]) SignedString(key interface{}) (string, error) {
5965
var sig, sstr string
6066
var err error
6167
if sstr, err = t.SigningString(); err != nil {
@@ -71,7 +77,7 @@ func (t *Token[T]) SignedString(key interface{}) (string, error) {
7177
// most expensive part of the whole deal. Unless you
7278
// need this for something special, just go straight for
7379
// the SignedString.
74-
func (t *Token[T]) SigningString() (string, error) {
80+
func (t *TokenFor[T]) SigningString() (string, error) {
7581
var err error
7682
var jsonValue []byte
7783

@@ -95,7 +101,7 @@ func (t *Token[T]) SigningString() (string, error) {
95101
// validate the 'alg' claim in the token matches the expected algorithm.
96102
// For more details about the importance of validating the 'alg' claim,
97103
// see https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/
98-
func Parse(tokenString string, keyFunc Keyfunc[MapClaims], options ...ParserOption) (*Token[MapClaims], error) {
104+
func Parse(tokenString string, keyFunc Keyfunc, options ...ParserOption) (*Token, error) {
99105
return NewParser(options...).Parse(tokenString, keyFunc)
100106
}
101107

@@ -104,7 +110,7 @@ func Parse(tokenString string, keyFunc Keyfunc[MapClaims], options ...ParserOpti
104110
// Note: If you provide a custom claim implementation that embeds one of the standard claims (such as RegisteredClaims),
105111
// make sure that a) you either embed a non-pointer version of the claims or b) if you are using a pointer, allocate the
106112
// proper memory for it before passing in the overall claims, otherwise you might run into a panic.
107-
func ParseWithClaims[T Claims](tokenString string, keyFunc Keyfunc[T], options ...ParserOption) (*Token[T], error) {
113+
func ParseWithClaims[T Claims](tokenString string, keyFunc KeyfuncFor[T], options ...ParserOption) (*TokenFor[T], error) {
108114
return NewParserFor[T](options...).Parse(tokenString, keyFunc)
109115
}
110116

token_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func TestToken_SigningString(t1 *testing.T) {
4040
}
4141
for _, tt := range tests {
4242
t1.Run(tt.name, func(t1 *testing.T) {
43-
t := &jwt.Token[jwt.Claims]{
43+
t := &jwt.TokenFor[jwt.Claims]{
4444
Raw: tt.fields.Raw,
4545
Method: tt.fields.Method,
4646
Header: tt.fields.Header,
@@ -61,7 +61,7 @@ func TestToken_SigningString(t1 *testing.T) {
6161
}
6262

6363
func BenchmarkToken_SigningString(b *testing.B) {
64-
t := &jwt.Token[jwt.Claims]{
64+
t := &jwt.TokenFor[jwt.Claims]{
6565
Method: jwt.SigningMethodHS256,
6666
Header: map[string]interface{}{
6767
"typ": "JWT",

0 commit comments

Comments
 (0)