Fix nonce error (#354)

* Adding a NonceError type to detect nonce errors

* Implement a one off retry on a nonce error.
This commit is contained in:
xenolf 2017-02-19 05:12:14 +01:00 committed by GitHub
parent 09d8a49bf2
commit 9f94aabbd2
2 changed files with 28 additions and 4 deletions

View file

@ -8,7 +8,10 @@ import (
"strings" "strings"
) )
const tosAgreementError = "Must agree to subscriber agreement before any further actions" const (
tosAgreementError = "Must agree to subscriber agreement before any further actions"
invalidNonceError = "JWS has invalid anti-replay nonce"
)
// RemoteError is the base type for all errors specific to the ACME protocol. // RemoteError is the base type for all errors specific to the ACME protocol.
type RemoteError struct { type RemoteError struct {
@ -28,6 +31,12 @@ type TOSError struct {
RemoteError RemoteError
} }
// NonceError represents the error which is returned if the
// nonce sent by the client was not accepted by the server.
type NonceError struct {
RemoteError
}
type domainError struct { type domainError struct {
Domain string Domain string
Error error Error error
@ -73,6 +82,10 @@ func handleHTTPError(resp *http.Response) error {
return TOSError{errorDetail} return TOSError{errorDetail}
} }
if errorDetail.StatusCode == http.StatusBadRequest && strings.HasPrefix(errorDetail.Detail, invalidNonceError) {
return NonceError{errorDetail}
}
return errorDetail return errorDetail
} }

View file

@ -41,15 +41,26 @@ func (j *jws) post(url string, content []byte) (*http.Response, error) {
} }
resp, err := httpPost(url, "application/jose+json", bytes.NewBuffer([]byte(signedContent.FullSerialize()))) resp, err := httpPost(url, "application/jose+json", bytes.NewBuffer([]byte(signedContent.FullSerialize())))
if err != nil {
return nil, err
}
// Even in case of an error, the response should still contain a nonce.
nonce, nonceErr := getNonceFromResponse(resp) nonce, nonceErr := getNonceFromResponse(resp)
if nonceErr == nil { if nonceErr == nil {
j.nonces.Push(nonce) j.nonces.Push(nonce)
} }
if err != nil {
switch err.(type) {
case NonceError:
// In case of a nonce error - retry once
resp, err = httpPost(url, "application/jose+json", bytes.NewBuffer([]byte(signedContent.FullSerialize())))
if err != nil {
return nil, err
}
default:
return nil, err
}
}
return resp, err return resp, err
} }