1- import time
21from datetime import datetime , timezone
32
43import click
54from jumpstarter_cli_common .config import opt_config
6- from jumpstarter_cli_common .oidc import decode_jwt
5+ from jumpstarter_cli_common .oidc import (
6+ TOKEN_EXPIRY_WARNING_SECONDS ,
7+ decode_jwt ,
8+ format_duration ,
9+ get_token_remaining_seconds ,
10+ )
711
812
913@click .group ()
1014def auth ():
11- """
12- Authentication and token management commands
13- """
15+ """Authentication and token management commands."""
16+
17+
18+ def _print_token_status (remaining : float ) -> None :
19+ """Print token status message based on remaining time."""
20+ duration = format_duration (remaining )
21+
22+ if remaining < 0 :
23+ click .echo (click .style (f"Status: EXPIRED ({ duration } ago)" , fg = "red" , bold = True ))
24+ click .echo (click .style ("Run 'jmp login' to refresh your credentials." , fg = "yellow" ))
25+ elif remaining < TOKEN_EXPIRY_WARNING_SECONDS :
26+ click .echo (click .style (f"Status: EXPIRING SOON ({ duration } remaining)" , fg = "red" , bold = True ))
27+ click .echo (click .style ("Run 'jmp login' to refresh your credentials." , fg = "yellow" ))
28+ elif remaining < 3600 :
29+ click .echo (click .style (f"Status: Valid ({ duration } remaining)" , fg = "yellow" ))
30+ else :
31+ click .echo (click .style (f"Status: Valid ({ duration } remaining)" , fg = "green" ))
1432
1533
1634@auth .command (name = "status" )
1735@opt_config (exporter = False )
1836def token_status (config ):
19- """
20- Display token status and expiry information
21- """
37+ """Display token status and expiry information."""
2238 token_str = getattr (config , "token" , None )
2339
2440 if not token_str :
@@ -27,40 +43,25 @@ def token_status(config):
2743
2844 try :
2945 payload = decode_jwt (token_str )
30- except Exception as e :
46+ except ValueError as e :
3147 click .echo (click .style (f"Failed to decode token: { e } " , fg = "red" ))
3248 return
3349
34- exp = payload . get ( "exp" )
35- if not exp :
50+ remaining = get_token_remaining_seconds ( token_str )
51+ if remaining is None :
3652 click .echo (click .style ("Token has no expiry claim" , fg = "yellow" ))
3753 return
3854
39- remaining = exp - time . time ( )
55+ exp = payload . get ( "exp" )
4056 exp_dt = datetime .fromtimestamp (exp , tz = timezone .utc )
57+ click .echo (f"Token expiry: { exp_dt .strftime ('%Y-%m-%d %H:%M:%S %Z' )} " )
4158
42- click .echo (f"Token expiry: { exp_dt .strftime ('%Y-%m-%d %H:%M:%S' )} " )
43-
44- if remaining < 0 :
45- hours = int (abs (remaining ) / 3600 )
46- mins = int ((abs (remaining ) % 3600 ) / 60 )
47- click .echo (click .style (f"Status: EXPIRED ({ hours } h { mins } m ago)" , fg = "red" , bold = True ))
48- click .echo (click .style ("Run 'jmp login' to refresh your credentials." , fg = "yellow" ))
49- elif remaining < 300 : # Less than 5 minutes
50- mins = int (remaining / 60 )
51- secs = int (remaining % 60 )
52- click .echo (click .style (f"Status: EXPIRING SOON ({ mins } m { secs } s remaining)" , fg = "red" , bold = True ))
53- click .echo (click .style ("Run 'jmp login' to refresh your credentials." , fg = "yellow" ))
54- elif remaining < 3600 : # Less than 1 hour
55- mins = int (remaining / 60 )
56- click .echo (click .style (f"Status: Valid ({ mins } m remaining)" , fg = "yellow" ))
57- else :
58- hours = int (remaining / 3600 )
59- mins = int ((remaining % 3600 ) / 60 )
60- click .echo (click .style (f"Status: Valid ({ hours } h { mins } m remaining)" , fg = "green" ))
59+ _print_token_status (remaining )
6160
6261 # Show additional token info
63- if payload .get ("sub" ):
64- click .echo (f"Subject: { payload .get ('sub' )} " )
65- if payload .get ("iss" ):
66- click .echo (f"Issuer: { payload .get ('iss' )} " )
62+ sub = payload .get ("sub" )
63+ iss = payload .get ("iss" )
64+ if sub :
65+ click .echo (f"Subject: { sub } " )
66+ if iss :
67+ click .echo (f"Issuer: { iss } " )
0 commit comments