Add support for jwt validation (#783)

pull/801/head
steveorourke 3 years ago committed by GitHub
parent 8cfa1e93b6
commit e40bece342
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      README.md
  2. 6
      baked_in.go
  3. 6
      doc.go
  4. 2
      regexes.go
  5. 5
      translations/en/en.go
  6. 5
      translations/en/en_test.go
  7. 36
      validator_test.go

@ -159,6 +159,7 @@ Baked-in Validations
| isbn10 | International Standard Book Number 10 | | isbn10 | International Standard Book Number 10 |
| isbn13 | International Standard Book Number 13 | | isbn13 | International Standard Book Number 13 |
| json | JSON | | json | JSON |
| jwt | JSON Web Token (JWT) |
| latitude | Latitude | | latitude | Latitude |
| longitude | Longitude | | longitude | Longitude |
| rgb | RGB String | | rgb | RGB String |

@ -181,6 +181,7 @@ var (
"url_encoded": isURLEncoded, "url_encoded": isURLEncoded,
"dir": isDir, "dir": isDir,
"json": isJSON, "json": isJSON,
"jwt": isJWT,
"hostname_port": isHostnamePort, "hostname_port": isHostnamePort,
"lowercase": isLowercase, "lowercase": isLowercase,
"uppercase": isUppercase, "uppercase": isUppercase,
@ -2235,6 +2236,11 @@ func isJSON(fl FieldLevel) bool {
panic(fmt.Sprintf("Bad field type %T", field.Interface())) panic(fmt.Sprintf("Bad field type %T", field.Interface()))
} }
// isJWT is the validation function for validating if the current field's value is a valid JWT string.
func isJWT(fl FieldLevel) bool {
return jWTRegex.MatchString(fl.Field().String())
}
// isHostnamePort validates a <dns>:<port> combination for fields typically used for socket address. // isHostnamePort validates a <dns>:<port> combination for fields typically used for socket address.
func isHostnamePort(fl FieldLevel) bool { func isHostnamePort(fl FieldLevel) bool {
val := fl.Field().String() val := fl.Field().String()

@ -811,6 +811,12 @@ This validates that a string value is valid JSON
Usage: json Usage: json
JWT String
This validates that a string value is a valid JWT
Usage: jwt
File path File path
This validates that a string value contains a valid file path and that This validates that a string value contains a valid file path and that

@ -48,6 +48,7 @@ const (
uRLEncodedRegexString = `^(?:[^%]|%[0-9A-Fa-f]{2})*$` uRLEncodedRegexString = `^(?:[^%]|%[0-9A-Fa-f]{2})*$`
hTMLEncodedRegexString = `&#[x]?([0-9a-fA-F]{2})|(&gt)|(&lt)|(&quot)|(&amp)+[;]?` hTMLEncodedRegexString = `&#[x]?([0-9a-fA-F]{2})|(&gt)|(&lt)|(&quot)|(&amp)+[;]?`
hTMLRegexString = `<[/]?([a-zA-Z]+).*?>` hTMLRegexString = `<[/]?([a-zA-Z]+).*?>`
jWTRegexString = "^[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]*$"
splitParamsRegexString = `'[^']*'|\S+` splitParamsRegexString = `'[^']*'|\S+`
bicRegexString = `^[A-Za-z]{6}[A-Za-z0-9]{2}([A-Za-z0-9]{3})?$` bicRegexString = `^[A-Za-z]{6}[A-Za-z0-9]{2}([A-Za-z0-9]{3})?$`
) )
@ -98,6 +99,7 @@ var (
uRLEncodedRegex = regexp.MustCompile(uRLEncodedRegexString) uRLEncodedRegex = regexp.MustCompile(uRLEncodedRegexString)
hTMLEncodedRegex = regexp.MustCompile(hTMLEncodedRegexString) hTMLEncodedRegex = regexp.MustCompile(hTMLEncodedRegexString)
hTMLRegex = regexp.MustCompile(hTMLRegexString) hTMLRegex = regexp.MustCompile(hTMLRegexString)
jWTRegex = regexp.MustCompile(jWTRegexString)
splitParamsRegex = regexp.MustCompile(splitParamsRegexString) splitParamsRegex = regexp.MustCompile(splitParamsRegexString)
bicRegex = regexp.MustCompile(bicRegexString) bicRegex = regexp.MustCompile(bicRegexString)
) )

@ -1284,6 +1284,11 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
translation: "{0} must be a valid json string", translation: "{0} must be a valid json string",
override: false, override: false,
}, },
{
tag: "jwt",
translation: "{0} must be a valid jwt string",
override: false,
},
{ {
tag: "lowercase", tag: "lowercase",
translation: "{0} must be a lowercase string", translation: "{0} must be a lowercase string",

@ -141,6 +141,7 @@ func TestTranslations(t *testing.T) {
UniqueArray [3]string `validate:"unique"` UniqueArray [3]string `validate:"unique"`
UniqueMap map[string]string `validate:"unique"` UniqueMap map[string]string `validate:"unique"`
JSONString string `validate:"json"` JSONString string `validate:"json"`
JWTString string `validate:"jwt"`
LowercaseString string `validate:"lowercase"` LowercaseString string `validate:"lowercase"`
UppercaseString string `validate:"uppercase"` UppercaseString string `validate:"uppercase"`
Datetime string `validate:"datetime=2006-01-02"` Datetime string `validate:"datetime=2006-01-02"`
@ -646,6 +647,10 @@ func TestTranslations(t *testing.T) {
ns: "Test.JSONString", ns: "Test.JSONString",
expected: "JSONString must be a valid json string", expected: "JSONString must be a valid json string",
}, },
{
ns: "Test.JWTString",
expected: "JWTString must be a valid jwt string",
},
{ {
ns: "Test.LowercaseString", ns: "Test.LowercaseString",
expected: "LowercaseString must be a lowercase string", expected: "LowercaseString must be a lowercase string",

@ -10787,6 +10787,42 @@ func TestJSONValidation(t *testing.T) {
}, "Bad field type int") }, "Bad field type int")
} }
func TestJWTValidation(t *testing.T) {
tests := []struct {
param string
expected bool
}{
{"eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiZ29waGVyIn0.O_bROM_szPq9qBql-XDHMranHwP48ODdoLICWzqBr_U", true},
{"acb123-_.def456-_.ghi789-_", true},
{"eyJhbGciOiJOT05FIn0.e30.", true},
{"eyJhbGciOiJOT05FIn0.e30.\n", false},
{"\x00.\x00.\x00", false},
{"", false},
}
validate := New()
for i, test := range tests {
errs := validate.Var(test.param, "jwt")
if test.expected {
if !IsEqual(errs, nil) {
t.Fatalf("Index: %d jwt failed Error: %s", i, errs)
}
} else {
if IsEqual(errs, nil) {
t.Fatalf("Index: %d jwt failed Error: %s", i, errs)
} else {
val := getError(errs, "", "")
if val.Tag() != "jwt" {
t.Fatalf("Index: %d jwt failed Error: %s", i, errs)
}
}
}
}
}
func Test_hostnameport_validator(t *testing.T) { func Test_hostnameport_validator(t *testing.T) {
type Host struct { type Host struct {
Addr string `validate:"hostname_port"` Addr string `validate:"hostname_port"`

Loading…
Cancel
Save