Skip to content

Commit 4760f60

Browse files
committed
Update CSRF token handling
1 parent e154781 commit 4760f60

19 files changed

+224
-314
lines changed

clients/baseclient/client_error.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ package baseclient
33
import (
44
"bytes"
55
"fmt"
6+
"net/http"
67
"time"
78

8-
strfmt "github.com/go-openapi/strfmt"
9+
"github.com/go-openapi/strfmt"
910

1011
"github.com/go-openapi/runtime"
1112
)
@@ -14,6 +15,7 @@ type ClientError struct {
1415
Code int
1516
Status string
1617
Description interface{}
18+
Headers http.Header
1719
}
1820

1921
func (ce *ClientError) Error() string {
@@ -36,6 +38,15 @@ func NewClientError(err error) error {
3638
return err
3739
}
3840

41+
func NewClientErrorFromHttpResponse(response *http.Response, description string) error {
42+
return &ClientError{
43+
Code: response.StatusCode,
44+
Status: response.Status,
45+
Description: description,
46+
Headers: response.Header,
47+
}
48+
}
49+
3950
func BuildErrorResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
4051
result := &ErrorResponse{
4152
Code: response.Code(),

clients/baseclient/client_util_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,39 +19,39 @@ var _ = Describe("ClientUtil", func() {
1919

2020
Context("when the backend returns status code with first digit 1 (1xx)", func() {
2121
It("Retry operation call is expected to be made", func() {
22-
err := ClientError{102, "Processing", "The request has been accepted but it's not yet complete"}
22+
err := ClientError{Code: 102, Status: "Processing", Description: "The request has been accepted but it's not yet complete"}
2323
result := shouldRetry(&err)
2424
Expect(result).To(Equal(true))
2525
})
2626
})
2727

2828
Context("when the backend returns status code with first digit 2 (2xx)", func() {
2929
It("Retry operation call shouldn't be made", func() {
30-
err := ClientError{200, "OK", "The request has succeeded"}
30+
err := ClientError{Code: 200, Status: "OK", Description: "The request has succeeded"}
3131
result := shouldRetry(&err)
3232
Expect(result).To(Equal(false))
3333
})
3434
})
3535

3636
Context("when the backend returns status code with first digit 3 (3xx)", func() {
3737
It("Retry operation call is expected to be made", func() {
38-
err := ClientError{301, "Moved Permanently", "URI of requested resource has been changed"}
38+
err := ClientError{Code: 301, Status: "Moved Permanently", Description: "URI of requested resource has been changed"}
3939
result := shouldRetry(&err)
4040
Expect(result).To(Equal(true))
4141
})
4242
})
4343

4444
Context("when the backend returns status code with first digit 4 (4xx)", func() {
4545
It("Retry operation call is expected to be made", func() {
46-
err := ClientError{404, "Not Found", "The server cannot find requested resource"}
46+
err := ClientError{Code: 404, Status: "Not Found", Description: "The server cannot find requested resource"}
4747
result := shouldRetry(&err)
4848
Expect(result).To(Equal(true))
4949
})
5050
})
5151

5252
Context("when the backend returns status code with first digit 5 (5xx)", func() {
5353
It("Retry operation call is expected to be made", func() {
54-
err := ClientError{500, "Internal Server Error", "The server got an invalid response"}
54+
err := ClientError{Code: 500, Status: "Internal Server Error", Description: "The server got an invalid response"}
5555
result := shouldRetry(&err)
5656
Expect(result).To(Equal(true))
5757
})
@@ -84,7 +84,7 @@ var _ = Describe("ClientUtil", func() {
8484
It("Callback with retry", func() {
8585
mockCallback := func() (interface{}, error) {
8686
toReturn := testStruct{}
87-
err := ClientError{404, "Not Found", "The server cannot find requesred resource"}
87+
err := ClientError{Code: 404, Status: "Not Found", Description: "The server cannot find requesred resource"}
8888
return toReturn, &err
8989
}
9090
result, err := CallWithRetry(mockCallback, 4, time.Duration(0))

clients/baseclient/test_token_factory.go

Lines changed: 0 additions & 23 deletions
This file was deleted.

clients/csrf/csrf_helper.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package csrf
2+
3+
import (
4+
"github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/csrf/csrf_parameters"
5+
"net/http"
6+
"sync"
7+
"time"
8+
)
9+
10+
const CookieHeader = "Cookie"
11+
12+
type CsrfTokenHelper struct {
13+
Header string
14+
Token string
15+
Cookies []*http.Cookie
16+
NonProtectedMethods map[string]struct{}
17+
LastUpdateTime time.Time
18+
Mutex sync.Mutex
19+
}
20+
21+
func (c *CsrfTokenHelper) IsProtectionRequired(req *http.Request) bool {
22+
_, present := c.NonProtectedMethods[req.Method]
23+
return !present
24+
}
25+
26+
func (c *CsrfTokenHelper) IsExpired(timeout time.Duration) bool {
27+
return c.LastUpdateTime.IsZero() || c.LastUpdateTime.Add(timeout).Before(time.Now())
28+
}
29+
30+
func (c *CsrfTokenHelper) Update(params csrf_parameters.CsrfParams) {
31+
c.Header = params.CsrfTokenHeader
32+
c.Token = params.CsrfTokenValue
33+
c.Cookies = params.Cookies
34+
c.LastUpdateTime = time.Now()
35+
}
36+
37+
func (c *CsrfTokenHelper) SetInRequest(req *http.Request) {
38+
req.Header.Set(c.Header, c.Token)
39+
UpdateCookiesIfNeeded(c.Cookies, req)
40+
}
41+
42+
func (c *CsrfTokenHelper) InvalidateToken() {
43+
c.LastUpdateTime = time.Time{}
44+
}
45+
46+
func UpdateCookiesIfNeeded(cookies []*http.Cookie, request *http.Request) {
47+
if len(cookies) == 0 {
48+
return
49+
}
50+
request.Header.Del(CookieHeader)
51+
for _, cookie := range cookies {
52+
request.AddCookie(cookie)
53+
}
54+
}
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package csrf_parameters
22

3-
type CsrfRequestHeader struct {
3+
import "net/http"
4+
5+
type CsrfParams struct {
46
CsrfTokenHeader string
57
CsrfTokenValue string
8+
Cookies []*http.Cookie
69
}

clients/csrf/csrf_token_fetcher.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
package csrf
22

3-
import (
4-
"net/http"
5-
6-
"github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/csrf/csrf_parameters"
7-
)
3+
import "github.com/cloudfoundry-incubator/multiapps-cli-plugin/clients/csrf/csrf_parameters"
84

95
type CsrfTokenFetcher interface {
10-
FetchCsrfToken(url string, currentRequest *http.Request) (*csrf_parameters.CsrfRequestHeader, error)
6+
FetchCsrfToken(url, authToken string) (csrf_parameters.CsrfParams, error)
117
}

clients/csrf/csrf_token_manager.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ package csrf
33
import "net/http"
44

55
type CsrfTokenManager interface {
6-
initializeToken(forceInitializing bool) error
7-
updateToken()
8-
refreshTokenIfNeeded(response *http.Response) (bool, error)
9-
updateCsrfTokenInRequest()
6+
updateToken(*http.Request) error
7+
invalidateToken()
108
}

0 commit comments

Comments
 (0)