Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introducing functional-style options for the Parser type #108

Merged
merged 5 commits into from Oct 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
29 changes: 26 additions & 3 deletions parser.go
Expand Up @@ -8,9 +8,32 @@ import (
)

type Parser struct {
ValidMethods []string // If populated, only these methods will be considered valid
UseJSONNumber bool // Use JSON Number format in JSON decoder
SkipClaimsValidation bool // Skip claims validation during token parsing
// If populated, only these methods will be considered valid.
//
// Deprecated: In future releases, this field will not be exported anymore and should be set with an option to NewParser instead.
ValidMethods []string
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we live in a world where algorithms are well defined, instead of strings?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably, at some future point. We should keep it in mind when de-exporting the field in the future.


// Use JSON Number format in JSON decoder.
//
// Deprecated: In future releases, this field will not be exported anymore and should be set with an option to NewParser instead.
UseJSONNumber bool

// Skip claims validation during token parsing.
//
// Deprecated: In future releases, this field will not be exported anymore and should be set with an option to NewParser instead.
SkipClaimsValidation bool
}

// NewParser creates a new Parser with the specified options
func NewParser(options ...ParserOption) *Parser {
p := &Parser{}

// loop through our parsing options and apply them
for _, option := range options {
option(p)
}

return p
}

// Parse parses, validates, and returns a token.
Expand Down
29 changes: 29 additions & 0 deletions parser_option.go
@@ -0,0 +1,29 @@
package jwt

// ParserOption is used to implement functional-style options that modify the behaviour of the parser. To add
// new options, just create a function (ideally beginning with With or Without) that returns an anonymous function that
// takes a *Parser type as input and manipulates its configuration accordingly.
type ParserOption func(*Parser)

// WithValidMethods is an option to supply algorithm methods that the parser will check. Only those methods will be considered valid.
// It is heavily encouraged to use this option in order to prevent attacks such as https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/.
func WithValidMethods(methods []string) ParserOption {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to have a unit test.

return func(p *Parser) {
p.ValidMethods = methods
}
}

// WithJSONNumber is an option to configure the underyling JSON parser with UseNumber
func WithJSONNumber() ParserOption {
return func(p *Parser) {
p.UseJSONNumber = true
}
}

// WithoutClaimsValidation is an option to disable claims validation. This option should only be used if you exactly know
// what you are doing.
func WithoutClaimsValidation() ParserOption {
return func(p *Parser) {
p.SkipClaimsValidation = true
}
}
8 changes: 4 additions & 4 deletions token.go
Expand Up @@ -85,12 +85,12 @@ func (t *Token) SigningString() (string, error) {
// Parse parses, validates, and returns a token.
// keyFunc will receive the parsed token and should return the key for validating.
// If everything is kosher, err will be nil
func Parse(tokenString string, keyFunc Keyfunc) (*Token, error) {
return new(Parser).Parse(tokenString, keyFunc)
func Parse(tokenString string, keyFunc Keyfunc, options ...ParserOption) (*Token, error) {
return NewParser(options...).Parse(tokenString, keyFunc)
}

func ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) {
return new(Parser).ParseWithClaims(tokenString, claims, keyFunc)
func ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc, options ...ParserOption) (*Token, error) {
return NewParser(options...).ParseWithClaims(tokenString, claims, keyFunc)
}

// EncodeSegment encodes a JWT specific base64url encoding with padding stripped
Expand Down