Skip to content

Commit

Permalink
Added jwt http timeout (#285)
Browse files Browse the repository at this point in the history
* Added jwt http timeout

Co-authored-by: Alessandro Peretti <[email protected]>
  • Loading branch information
alessandroperetti and Alessandro Peretti committed Jun 9, 2023
1 parent a271ad1 commit 807e8f2
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 5 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,7 @@ The following options are supported by the `jwt` backend when remote is set to t
| --------------------------- | --------- | :-------: | ------------------------------------------------------------- |
| auth_opt_jwt_host | | Y/N | API server host name or ip |
| auth_opt_jwt_port | | Y | TCP port number |
| auth_opt_jwt_http_timeout | 5 | N | Timeout in seconds for http client |
| auth_opt_jwt_getuser_uri | | Y | URI for check username/password |
| auth_opt_jwt_superuser_uri | | N | URI for check superuser |
| auth_opt_jwt_aclcheck_uri | | Y | URI for check acl |
Expand Down
19 changes: 14 additions & 5 deletions backends/jwt_remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ type remoteJWTChecker struct {
hostWhitelist []string
withTLS bool
verifyPeer bool

paramsMode string
httpMethod string
responseMode string
paramsMode string
httpMethod string
responseMode string
timeout int

options tokenOptions

Expand Down Expand Up @@ -152,7 +152,16 @@ func NewRemoteJWTChecker(authOpts map[string]string, options tokenOptions, versi
return nil, errors.Errorf("JWT backend error: missing remote options: %s", missingOpts)
}

checker.client = &h.Client{Timeout: 5 * time.Second}
checker.timeout = 5
if timeoutString, ok := authOpts["jwt_http_timeout"]; ok {
if timeout, err := strconv.Atoi(timeoutString); err == nil {
checker.timeout = timeout
} else {
log.Errorf("unable to parse timeout: %s", err)
}
}

checker.client = &h.Client{Timeout: time.Duration(checker.timeout) * time.Second}

if !checker.verifyPeer {
tr := &h.Transport{
Expand Down
85 changes: 85 additions & 0 deletions backends/jwt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1654,3 +1654,88 @@ func TestJWTFormTextResponseServer(t *testing.T) {
})

}

func TestJWTHttpTimeout(t *testing.T) {

topic := "test/topic"
var acc = int64(1)
clientID := "test_client"
token, _ := jwtToken.SignedString([]byte(jwtSecret))

version := "2.0.0"

mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)

err := r.ParseForm()
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}

var params = r.Form

gToken := r.Header.Get("Authorization")
gToken = strings.TrimPrefix(gToken, "Bearer ")

if token != gToken {
w.Write([]byte("Wrong credentials."))
return
}

switch r.URL.Path {
case "/user", "/superuser":
w.Write([]byte("ok"))
case "/acl":
time.Sleep(time.Duration(1200) * time.Millisecond)
paramsAcc, _ := strconv.ParseInt(params["acc"][0], 10, 64)
if params["topic"][0] == topic && params["clientid"][0] == clientID && paramsAcc <= acc {
w.Write([]byte("ok"))
break
}
w.Write([]byte("Acl check failed."))
}

}))

defer mockServer.Close()

authOpts := make(map[string]string)
authOpts["jwt_mode"] = "remote"
authOpts["jwt_params_mode"] = "form"
authOpts["jwt_response_mode"] = "text"
authOpts["jwt_host"] = strings.Replace(mockServer.URL, "http:https://", "", -1)
authOpts["jwt_port"] = ""
authOpts["jwt_getuser_uri"] = "/user"
authOpts["jwt_superuser_uri"] = "/superuser"
authOpts["jwt_aclcheck_uri"] = "/acl"
authOpts["jwt_http_timeout"] = "1"

Convey("Given correct options an http backend instance should be returned", t, func() {
hb, err := NewJWT(authOpts, log.DebugLevel, hashing.NewHasher(authOpts, ""), version)
So(err, ShouldBeNil)

Convey("JWT remote test timeout parameter: YES TIMEOUT", func() {
_, err := hb.CheckAcl(token, topic, clientID, MOSQ_ACL_READ)
So(err, ShouldBeError)
So(err.Error(), ShouldContainSubstring, "acl")
})

hb.Halt()
})

authOpts["jwt_http_timeout"] = "2"

Convey("Given correct options an http backend instance should be returned", t, func() {
hb, err := NewJWT(authOpts, log.DebugLevel, hashing.NewHasher(authOpts, ""), version)
So(err, ShouldBeNil)

Convey("JWT remote test timeout parameter: NO TIMEOUT", func() {
_, err := hb.CheckAcl(token, topic, clientID, MOSQ_ACL_READ)
So(err, ShouldBeNil)
})

hb.Halt()
})

}

0 comments on commit 807e8f2

Please sign in to comment.