Skip to content

Commit

Permalink
feat: implement token expiration check to reuse valid tokens during l…
Browse files Browse the repository at this point in the history
…ogin

- Added `isTokenExpired` function to decode JWT token and verify its expiration (`exp` field).
- Modified `executeLogin` to reuse existing tokens if they are still valid, avoiding unnecessary credential prompts.
- Enhanced user experience by skipping login credentials input when a valid token is available.

Signed-off-by: Youngjin Jo <[email protected]>
  • Loading branch information
yjinjo committed Nov 8, 2024
1 parent 3920b0f commit 6dbf48c
Showing 1 changed file with 39 additions and 5 deletions.
44 changes: 39 additions & 5 deletions cmd/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ package cmd

import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"regexp"
"strings"
"time"

"github.com/pterm/pterm"
"github.com/spf13/cobra"
Expand All @@ -27,12 +30,14 @@ It will prompt you for your User ID, Password, and fetch the Domain ID automatic

func executeLogin(cmd *cobra.Command, args []string) {
if token := viper.GetString("token"); token != "" {
pterm.Info.Println("Existing token found, attempting to authenticate with saved credentials.")
if verifyToken(token) {
pterm.Success.Println("Successfully authenticated with saved token.")
return
if !isTokenExpired(token) {
pterm.Info.Println("Existing token found and it is still valid. Attempting to authenticate with saved credentials.")
if verifyToken(token) {
pterm.Success.Println("Successfully authenticated with saved token.")
return
}
}
pterm.Warning.Println("Saved token is invalid or expired, proceeding with login.")
pterm.Warning.Println("Saved token is expired or invalid, proceeding with login.")
}

if url == "" {
Expand Down Expand Up @@ -92,6 +97,35 @@ func executeLogin(cmd *cobra.Command, args []string) {
pterm.Success.Println("Successfully logged in and saved token.")
}

func isTokenExpired(token string) bool {
parts := strings.Split(token, ".")
if len(parts) != 3 {
pterm.Error.Println("Invalid token format.")
return true
}

payload, err := base64.RawURLEncoding.DecodeString(parts[1])
if err != nil {
pterm.Error.Println("Failed to decode token payload:", err)
return true
}

var claims map[string]interface{}
if err := json.Unmarshal(payload, &claims); err != nil {
pterm.Error.Println("Failed to unmarshal token payload:", err)
return true
}

exp, ok := claims["exp"].(float64)
if !ok {
pterm.Error.Println("Expiration time (exp) not found in token.")
return true
}

expirationTime := time.Unix(int64(exp), 0)
return time.Now().After(expirationTime)
}

func promptCredentials() (string, string) {
userId, _ := pterm.DefaultInteractiveTextInput.Show("Enter your user ID")
passwordInput := pterm.DefaultInteractiveTextInput.WithMask("*")
Expand Down

0 comments on commit 6dbf48c

Please sign in to comment.