Skip to content
This repository was archived by the owner on Aug 10, 2021. It is now read-only.

Commit

Permalink
Fix security vulnerability
Browse files Browse the repository at this point in the history
Fixes a security vulnerability where a jwt token could potentially be validated having invalid string characters.
  • Loading branch information
giorgos-f3 committed Jun 24, 2021
1 parent 5b2d2b5 commit bc6d185
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 16 deletions.
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/form3tech-oss/jwt-go

go 1.16
44 changes: 28 additions & 16 deletions map_claims.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,30 +36,38 @@ func (m MapClaims) VerifyAudience(cmp string, req bool) bool {
// Compares the exp claim against cmp.
// 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 {
switch exp := m["exp"].(type) {
exp, ok := m["exp"]
if !ok {
return !req
}
switch expType := exp.(type) {
case float64:
return verifyExp(int64(exp), cmp, req)
return verifyExp(int64(expType), cmp, req)
case json.Number:
v, _ := exp.Int64()
v, _ := expType.Int64()
return verifyExp(v, cmp, req)
}
return req == false
return false
}

// Compares the iat claim against cmp.
// 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 {
switch iat := m["iat"].(type) {
iat, ok := m["iat"]
if !ok {
return !req
}
switch iatType := iat.(type) {
case float64:
return verifyIat(int64(iat), cmp, req)
return verifyIat(int64(iatType), cmp, req)
case json.Number:
v, _ := iat.Int64()
v, _ := iatType.Int64()
return verifyIat(v, cmp, req)
}
return req == false
return false
}

// Compares the iss claim against cmp.
// Compares the iss claim against cmp.``
// 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 {
iss, _ := m["iss"].(string)
Expand All @@ -69,14 +77,18 @@ func (m MapClaims) VerifyIssuer(cmp string, req bool) bool {
// Compares the nbf claim against cmp.
// 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 {
switch nbf := m["nbf"].(type) {
nbf, ok := m["nbf"]
if !ok {
return !req
}
switch nbfType := nbf.(type) {
case float64:
return verifyNbf(int64(nbf), cmp, req)
return verifyNbf(int64(nbfType), cmp, req)
case json.Number:
v, _ := nbf.Int64()
v, _ := nbfType.Int64()
return verifyNbf(v, cmp, req)
}
return req == false
return false
}

// Validates time based claims "exp, iat, nbf".
Expand All @@ -87,17 +99,17 @@ func (m MapClaims) Valid() error {
vErr := new(ValidationError)
now := TimeFunc().Unix()

if m.VerifyExpiresAt(now, false) == false {
if !m.VerifyExpiresAt(now, false) {
vErr.Inner = errors.New("Token is expired")
vErr.Errors |= ValidationErrorExpired
}

if m.VerifyIssuedAt(now, false) == false {
if !m.VerifyIssuedAt(now, false) {
vErr.Inner = errors.New("Token used before issued")
vErr.Errors |= ValidationErrorIssuedAt
}

if m.VerifyNotBefore(now, false) == false {
if !m.VerifyNotBefore(now, false) {
vErr.Inner = errors.New("Token is not valid yet")
vErr.Errors |= ValidationErrorNotValidYet
}
Expand Down
35 changes: 35 additions & 0 deletions map_claims_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,41 @@ func Test_mapClaims_string_aud_fail(t *testing.T) {
want := false
got := mapClaims.VerifyAudience("foo", true)

if want != got {
t.Fatalf("Failed to verify claims, wanted: %v got %v", want, got)
}

}

func Test_mapclaims_verify_issued_at_invalid_type_string(t *testing.T) {
mapClaims := MapClaims{
"iat": "foo",
}
want := false
got := mapClaims.VerifyIssuedAt(0, false)
if want != got {
t.Fatalf("Failed to verify claims, wanted: %v got %v", want, got)
}
}

func Test_mapclaims_verify_not_before_invalid_type_string(t *testing.T) {
mapClaims := MapClaims{
"nbf": "foo",
}
want := false
got := mapClaims.VerifyNotBefore(0, false)
if want != got {
t.Fatalf("Failed to verify claims, wanted: %v got %v", want, got)
}
}

func Test_mapclaims_verify_expires_at_invalid_type_string(t *testing.T) {
mapClaims := MapClaims{
"exp": "foo",
}
want := false
got := mapClaims.VerifyExpiresAt(0, false)

if want != got {
t.Fatalf("Failed to verify claims, wanted: %v got %v", want, got)
}
Expand Down

0 comments on commit bc6d185

Please sign in to comment.