mirror of https://github.com/golang-jwt/jwt.git
gracefully handle a nil keyfunc passed to Parse. (and more tests)
This commit is contained in:
parent
e1571c8f04
commit
4beb9b5850
5
jwt.go
5
jwt.go
|
@ -127,7 +127,12 @@ func Parse(tokenString string, keyFunc Keyfunc) (*Token, error) {
|
||||||
|
|
||||||
// Lookup key
|
// Lookup key
|
||||||
var key interface{}
|
var key interface{}
|
||||||
|
if keyFunc == nil {
|
||||||
|
// keyFunc was not provided. short circuiting validation
|
||||||
|
return token, &ValidationError{err: "no Keyfunc was provided.", Errors: ValidationErrorUnverifiable}
|
||||||
|
}
|
||||||
if key, err = keyFunc(token); err != nil {
|
if key, err = keyFunc(token); err != nil {
|
||||||
|
// keyFunc returned an error
|
||||||
return token, &ValidationError{err: err.Error(), Errors: ValidationErrorUnverifiable}
|
return token, &ValidationError{err: err.Error(), Errors: ValidationErrorUnverifiable}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
59
jwt_test.go
59
jwt_test.go
|
@ -9,9 +9,18 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
jwtTestDefaultKey []byte
|
||||||
|
defaultKeyFunc Keyfunc = func(t *Token) (interface{}, error) { return jwtTestDefaultKey, nil }
|
||||||
|
emptyKeyFunc Keyfunc = func(t *Token) (interface{}, error) { return nil, nil }
|
||||||
|
errorKeyFunc Keyfunc = func(t *Token) (interface{}, error) { return nil, fmt.Errorf("error loading key") }
|
||||||
|
nilKeyFunc Keyfunc = nil
|
||||||
|
)
|
||||||
|
|
||||||
var jwtTestData = []struct {
|
var jwtTestData = []struct {
|
||||||
name string
|
name string
|
||||||
tokenString string
|
tokenString string
|
||||||
|
keyfunc Keyfunc
|
||||||
claims map[string]interface{}
|
claims map[string]interface{}
|
||||||
valid bool
|
valid bool
|
||||||
validationError *ValidationError
|
validationError *ValidationError
|
||||||
|
@ -19,6 +28,7 @@ var jwtTestData = []struct {
|
||||||
{
|
{
|
||||||
"basic",
|
"basic",
|
||||||
"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg",
|
"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg",
|
||||||
|
defaultKeyFunc,
|
||||||
map[string]interface{}{"foo": "bar"},
|
map[string]interface{}{"foo": "bar"},
|
||||||
true,
|
true,
|
||||||
nil,
|
nil,
|
||||||
|
@ -26,6 +36,7 @@ var jwtTestData = []struct {
|
||||||
{
|
{
|
||||||
"basic expired",
|
"basic expired",
|
||||||
"", // autogen
|
"", // autogen
|
||||||
|
defaultKeyFunc,
|
||||||
map[string]interface{}{"foo": "bar", "exp": float64(time.Now().Unix() - 100)},
|
map[string]interface{}{"foo": "bar", "exp": float64(time.Now().Unix() - 100)},
|
||||||
false,
|
false,
|
||||||
&ValidationError{Errors: ValidationErrorExpired},
|
&ValidationError{Errors: ValidationErrorExpired},
|
||||||
|
@ -33,6 +44,7 @@ var jwtTestData = []struct {
|
||||||
{
|
{
|
||||||
"basic nbf",
|
"basic nbf",
|
||||||
"", // autogen
|
"", // autogen
|
||||||
|
defaultKeyFunc,
|
||||||
map[string]interface{}{"foo": "bar", "nbf": float64(time.Now().Unix() + 100)},
|
map[string]interface{}{"foo": "bar", "nbf": float64(time.Now().Unix() + 100)},
|
||||||
false,
|
false,
|
||||||
&ValidationError{Errors: ValidationErrorNotValidYet},
|
&ValidationError{Errors: ValidationErrorNotValidYet},
|
||||||
|
@ -40,6 +52,7 @@ var jwtTestData = []struct {
|
||||||
{
|
{
|
||||||
"expired and nbf",
|
"expired and nbf",
|
||||||
"", // autogen
|
"", // autogen
|
||||||
|
defaultKeyFunc,
|
||||||
map[string]interface{}{"foo": "bar", "nbf": float64(time.Now().Unix() + 100), "exp": float64(time.Now().Unix() - 100)},
|
map[string]interface{}{"foo": "bar", "nbf": float64(time.Now().Unix() + 100), "exp": float64(time.Now().Unix() - 100)},
|
||||||
false,
|
false,
|
||||||
&ValidationError{Errors: ValidationErrorNotValidYet | ValidationErrorExpired},
|
&ValidationError{Errors: ValidationErrorNotValidYet | ValidationErrorExpired},
|
||||||
|
@ -47,10 +60,42 @@ var jwtTestData = []struct {
|
||||||
{
|
{
|
||||||
"basic invalid",
|
"basic invalid",
|
||||||
"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.EhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg",
|
"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.EhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg",
|
||||||
|
defaultKeyFunc,
|
||||||
map[string]interface{}{"foo": "bar"},
|
map[string]interface{}{"foo": "bar"},
|
||||||
false,
|
false,
|
||||||
&ValidationError{Errors: ValidationErrorSignatureInvalid},
|
&ValidationError{Errors: ValidationErrorSignatureInvalid},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"basic nokeyfunc",
|
||||||
|
"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg",
|
||||||
|
nilKeyFunc,
|
||||||
|
map[string]interface{}{"foo": "bar"},
|
||||||
|
false,
|
||||||
|
&ValidationError{Errors: ValidationErrorUnverifiable},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"basic nokey",
|
||||||
|
"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg",
|
||||||
|
emptyKeyFunc,
|
||||||
|
map[string]interface{}{"foo": "bar"},
|
||||||
|
false,
|
||||||
|
&ValidationError{Errors: ValidationErrorSignatureInvalid},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"basic errorkey",
|
||||||
|
"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg",
|
||||||
|
errorKeyFunc,
|
||||||
|
map[string]interface{}{"foo": "bar"},
|
||||||
|
false,
|
||||||
|
&ValidationError{Errors: ValidationErrorUnverifiable},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
var e error
|
||||||
|
if jwtTestDefaultKey, e = ioutil.ReadFile("test/sample_key.pub"); e != nil {
|
||||||
|
panic(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeSample(c map[string]interface{}) string {
|
func makeSample(c map[string]interface{}) string {
|
||||||
|
@ -71,16 +116,11 @@ func makeSample(c map[string]interface{}) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestJWT(t *testing.T) {
|
func TestJWT(t *testing.T) {
|
||||||
key, e := ioutil.ReadFile("test/sample_key.pub")
|
|
||||||
if e != nil {
|
|
||||||
t.Fatal(e)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, data := range jwtTestData {
|
for _, data := range jwtTestData {
|
||||||
if data.tokenString == "" {
|
if data.tokenString == "" {
|
||||||
data.tokenString = makeSample(data.claims)
|
data.tokenString = makeSample(data.claims)
|
||||||
}
|
}
|
||||||
token, err := Parse(data.tokenString, func(t *Token) (interface{}, error) { return key, nil })
|
token, err := Parse(data.tokenString, data.keyfunc)
|
||||||
|
|
||||||
if !reflect.DeepEqual(data.claims, token.Claims) {
|
if !reflect.DeepEqual(data.claims, token.Claims) {
|
||||||
t.Errorf("[%v] Claims mismatch. Expecting: %v Got: %v", data.name, data.claims, token.Claims)
|
t.Errorf("[%v] Claims mismatch. Expecting: %v Got: %v", data.name, data.claims, token.Claims)
|
||||||
|
@ -107,11 +147,6 @@ func TestJWT(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseRequest(t *testing.T) {
|
func TestParseRequest(t *testing.T) {
|
||||||
key, e := ioutil.ReadFile("test/sample_key.pub")
|
|
||||||
if e != nil {
|
|
||||||
t.Fatal(e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bearer token request
|
// Bearer token request
|
||||||
for _, data := range jwtTestData {
|
for _, data := range jwtTestData {
|
||||||
if data.tokenString == "" {
|
if data.tokenString == "" {
|
||||||
|
@ -120,7 +155,7 @@ func TestParseRequest(t *testing.T) {
|
||||||
|
|
||||||
r, _ := http.NewRequest("GET", "/", nil)
|
r, _ := http.NewRequest("GET", "/", nil)
|
||||||
r.Header.Set("Authorization", fmt.Sprintf("Bearer %v", data.tokenString))
|
r.Header.Set("Authorization", fmt.Sprintf("Bearer %v", data.tokenString))
|
||||||
token, err := ParseFromRequest(r, func(t *Token) (interface{}, error) { return key, nil })
|
token, err := ParseFromRequest(r, data.keyfunc)
|
||||||
|
|
||||||
if !reflect.DeepEqual(data.claims, token.Claims) {
|
if !reflect.DeepEqual(data.claims, token.Claims) {
|
||||||
t.Errorf("[%v] Claims mismatch. Expecting: %v Got: %v", data.name, data.claims, token.Claims)
|
t.Errorf("[%v] Claims mismatch. Expecting: %v Got: %v", data.name, data.claims, token.Claims)
|
||||||
|
|
Loading…
Reference in New Issue