Skip to content

Commit 5d40225

Browse files
authored
fix: Better error on expired token (#90)
Co-authored-by: Kemal Hadimli <disq@users.noreply.github.com>
1 parent cc496c5 commit 5d40225

File tree

2 files changed

+49
-10
lines changed

2 files changed

+49
-10
lines changed

auth/token.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,10 @@ func (tc *TokenClient) GetToken() (Token, error) {
8484
}
8585
tokenResponse, err := tc.generateToken(refreshToken)
8686
if err != nil {
87-
return UndefinedToken, fmt.Errorf("failed to sign in with custom token: %w", err)
87+
if IsTokenExpiredError(err) {
88+
return UndefinedToken, fmt.Errorf("authentication token expired: %w. Hint: You may need to run `cloudquery login` or set %s", err, EnvVarCloudQueryAPIKey)
89+
}
90+
return UndefinedToken, fmt.Errorf("failed to sign in with token: %w", err)
8891
}
8992

9093
if err := SaveRefreshToken(tokenResponse.RefreshToken); err != nil {
@@ -116,19 +119,16 @@ func (tc *TokenClient) generateToken(refreshToken string) (*tokenResponse, error
116119
return nil, err
117120
}
118121
defer resp.Body.Close()
119-
if resp.StatusCode != http.StatusOK {
120-
body, readErr := io.ReadAll(resp.Body)
121-
if readErr != nil {
122-
return nil, fmt.Errorf("failed to read response body: %w", readErr)
123-
}
124-
return nil, fmt.Errorf("failed to refresh token: %s: %s", resp.Status, body)
125-
}
126-
127-
var tr tokenResponse
128122
body, err := io.ReadAll(resp.Body)
129123
if err != nil {
130124
return nil, err
131125
}
126+
127+
if resp.StatusCode != http.StatusOK {
128+
return nil, fmt.Errorf("failed to refresh token: %s: %w", resp.Status, TokenErrorFromBody(body))
129+
}
130+
131+
var tr tokenResponse
132132
if err := parseToken(body, &tr); err != nil {
133133
return nil, err
134134
}

auth/token_error.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package auth
2+
3+
import (
4+
"encoding/json"
5+
"errors"
6+
)
7+
8+
type TokenError struct {
9+
Body []byte `json:"-"`
10+
ErrorDetails struct {
11+
Code int `json:"code"`
12+
Message string `json:"message"`
13+
Status string `json:"status"`
14+
} `json:"error"`
15+
}
16+
17+
func (t TokenError) Error() string {
18+
return string(t.Body)
19+
}
20+
21+
func TokenErrorFromBody(body []byte) *TokenError {
22+
t := &TokenError{}
23+
_ = json.Unmarshal(body, t)
24+
t.Body = body
25+
return t
26+
}
27+
28+
func IsTokenExpiredError(err error) bool {
29+
if err == nil {
30+
return false
31+
}
32+
33+
var te *TokenError
34+
if errors.As(err, &te) {
35+
return te.ErrorDetails.Code == 400 && te.ErrorDetails.Message == "TOKEN_EXPIRED"
36+
}
37+
38+
return false
39+
}

0 commit comments

Comments
 (0)