Skip to content

Commit 6819082

Browse files
committed
Fix expired tokens not refreshing.
Add 'id' command to show user-id, as well as log it during authentication.
1 parent 847be57 commit 6819082

4 files changed

Lines changed: 69 additions & 22 deletions

File tree

cmd/common/config.go

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const (
2525
// and NOT used by themselves.
2626
AccessTokenConfigKey = "access-token" // user-scoped API access token key
2727
RefreshTokenConfigKey = "refresh-token" // user-scoped API refresh token key
28+
TokenIDConfigKey = "user-id" // user-scoped token ID
2829
APIAccessTokenConfigKeyPartial = "api-token" // app- or org-scoped API token key
2930
APIRefreshTokenConfigKeyPartial = "api-refresh-token" // app- or org-scoped API token key
3031
AccountConfigKeyPartial = "account" // app-scoped account ID key
@@ -72,10 +73,39 @@ func InitConfig() {
7273

7374
if Verbose {
7475
fmt.Println("Using configuration:", viper.ConfigFileUsed())
76+
fmt.Println(viper.AllSettings())
7577
}
7678
}
7779
}
7880

81+
// DecodeUserID parses the user access token to get out the "prvd"->"user_id" field.
82+
// Requires the user access token be setup already (i.e. authenticate has been called)
83+
func DecodeUserID() string {
84+
rawToken := RequireUserAccessToken()
85+
86+
var jwtParser jwt.Parser
87+
token, _, err := jwtParser.ParseUnverified(rawToken, jwt.MapClaims{})
88+
if err != nil {
89+
log.Printf("failed to parse JWT token on behalf of authorized user; %s", err.Error())
90+
os.Exit(1)
91+
}
92+
93+
claims := token.Claims.(jwt.MapClaims)
94+
prvd := claims["prvd"]
95+
if prvd == nil {
96+
log.Printf("failed to get 'prvd' field from token")
97+
os.Exit(1)
98+
}
99+
100+
if userID, ok := prvd.(map[string]interface{})["user_id"].(string); ok {
101+
return userID
102+
}
103+
104+
log.Printf("failed to get 'user_id' field from token")
105+
os.Exit(1)
106+
return ""
107+
}
108+
79109
func RequireUserAccessToken() string {
80110
token := ""
81111
if viper.IsSet(AccessTokenConfigKey) {
@@ -123,6 +153,8 @@ func CacheAccessRefreshToken(token *ident.Token) {
123153
viper.Set(RefreshTokenConfigKey, *token.RefreshToken)
124154
}
125155

156+
viper.Set(TokenIDConfigKey, token.ID.String())
157+
126158
viper.WriteConfig()
127159
}
128160

@@ -217,28 +249,16 @@ func BuildConfigKeyWithUser(keyPartial, userID string) string {
217249
}
218250

219251
func isTokenExpired(bearerToken string) bool {
220-
token, err := jwt.Parse(bearerToken, func(_jwtToken *jwt.Token) (interface{}, error) {
221-
// uncomment when enabling local verification
222-
// var kid *string
223-
// if kidhdr, ok := _jwtToken.Header["kid"].(string); ok {
224-
// kid = &kidhdr
225-
// }
226-
227-
// publicKey, _, _, _ := util.ResolveJWTKeypair(kid)
228-
// if publicKey == nil {
229-
// msg := "failed to resolve a valid JWT verification key"
230-
// if kid != nil {
231-
// msg = fmt.Sprintf("%s; invalid kid specified in header: %s", msg, *kid)
232-
// } else {
233-
// msg = fmt.Sprintf("%s; no default verification key configured", msg)
234-
// }
235-
// return nil, fmt.Errorf(msg)
236-
// }
237-
238-
return nil, nil
239-
})
252+
253+
var jwtParser jwt.Parser
254+
token, _, err := jwtParser.ParseUnverified(bearerToken, jwt.MapClaims{})
255+
if err != nil {
256+
log.Printf("failed to parse JWT token on behalf of authorized user; %s", err.Error())
257+
os.Exit(1)
258+
}
240259

241260
if err != nil {
261+
log.Printf("isTokenExpired err: %s", err)
242262
return false
243263
}
244264

cmd/root.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ func init() {
5151
rootCmd.AddCommand(api_tokens.APITokensCmd)
5252
rootCmd.AddCommand(applications.ApplicationsCmd)
5353
rootCmd.AddCommand(users.AuthenticateCmd)
54+
rootCmd.AddCommand(users.ShowIDCmd)
5455
rootCmd.AddCommand(baseledger.BaseledgerCmd)
5556
rootCmd.AddCommand(baseline.BaselineCmd)
5657
rootCmd.AddCommand(connectors.ConnectorsCmd)

cmd/users/authenticate.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
"github.com/spf13/viper"
1212
)
1313

14-
// authenticateCmd represents the authenticate command
14+
// AuthenticateCmd represents the authenticate command
1515
var AuthenticateCmd = &cobra.Command{
1616
Use: "authenticate",
1717
Short: "Authenticate using your credentials",
@@ -34,9 +34,13 @@ func authenticate(cmd *cobra.Command, args []string) {
3434
common.CacheAccessRefreshToken(resp.Token)
3535
} else if resp.Token.Token != nil {
3636
cacheAPIToken(*resp.Token.Token)
37+
} else {
38+
log.Println("Failed to get token from authentication response.")
39+
os.Exit(1)
3740
}
3841

39-
log.Printf("Authentication successful")
42+
log.Print("Authentication successful")
43+
log.Printf("User ID: %s", common.DecodeUserID())
4044
}
4145

4246
func cacheAPIToken(token string) {

cmd/users/showid.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package users
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/provideplatform/provide-cli/cmd/common"
7+
8+
"github.com/spf13/cobra"
9+
)
10+
11+
// ShowIDCmd represents the id command
12+
var ShowIDCmd = &cobra.Command{
13+
Use: "id",
14+
Short: "Prints out the ID of the currently authenticated user",
15+
Long: "Prints out the ID of the currently authenticated user",
16+
Run: showid,
17+
}
18+
19+
func showid(cmd *cobra.Command, args []string) {
20+
id := common.DecodeUserID()
21+
fmt.Println(id)
22+
}

0 commit comments

Comments
 (0)