Skip to content
This repository was archived by the owner on Jan 23, 2026. It is now read-only.

Commit 864e2d8

Browse files
authored
Merge pull request #797 from bennyz/force-login
cli: add jmp login --force
2 parents cea4061 + 8ac7256 commit 864e2d8

3 files changed

Lines changed: 21 additions & 8 deletions

File tree

packages/jumpstarter-cli-common/jumpstarter_cli_common/oidc.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ async def password_grant(self, username: str, password: str):
8282
)
8383
)
8484

85-
async def authorization_code_grant(self, callback_port: int | None = None):
85+
async def authorization_code_grant(self, callback_port: int | None = None, prompt: str | None = None):
8686
config = await self.configuration()
8787

8888
# Use provided port, fall back to env var, then default to 0 (OS picks)
@@ -120,7 +120,12 @@ async def callback(request):
120120

121121
client = self.client(redirect_uri=redirect_uri)
122122

123-
uri, state = client.create_authorization_url(config["authorization_endpoint"])
123+
# Add prompt parameter if force requested
124+
auth_params = {}
125+
if prompt:
126+
auth_params["prompt"] = prompt
127+
128+
uri, state = client.create_authorization_url(config["authorization_endpoint"], **auth_params)
124129

125130
print("Please open the URL in browser: ", uri)
126131

packages/jumpstarter-cli/jumpstarter_cli/auth.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ def _print_token_status(remaining: float) -> None:
2121

2222
if remaining < 0:
2323
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"))
24+
click.echo(click.style("Run 'jmp login --force' to refresh your credentials.", fg="yellow"))
2525
elif remaining < TOKEN_EXPIRY_WARNING_SECONDS:
2626
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"))
27+
click.echo(click.style("Run 'jmp login --force' to refresh your credentials.", fg="yellow"))
2828
elif remaining < 3600:
2929
click.echo(click.style(f"Status: Valid ({duration} remaining)", fg="yellow"))
3030
else:

packages/jumpstarter-cli/jumpstarter_cli/login.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@
1919
@click.option("-e", "--endpoint", type=str, help="Enter the Jumpstarter service endpoint.", default=None)
2020
@click.option("--namespace", type=str, help="Enter the Jumpstarter exporter namespace.", default=None)
2121
@click.option("--name", type=str, help="Enter the Jumpstarter exporter name.", default=None)
22+
@click.option(
23+
"--force",
24+
is_flag=True,
25+
help="Force fresh login",
26+
default=False,
27+
)
2228
@opt_oidc
2329
# client specific
2430
# TODO: warn if used with exporter
@@ -52,6 +58,7 @@ async def login( # noqa: C901
5258
insecure_tls_config: bool,
5359
nointeractive: bool,
5460
allow,
61+
force: bool,
5562
):
5663
"""Login into a jumpstarter instance"""
5764

@@ -124,7 +131,8 @@ async def login( # noqa: C901
124131
elif username is not None and password is not None:
125132
tokens = await oidc.password_grant(username, password)
126133
else:
127-
tokens = await oidc.authorization_code_grant(callback_port=callback_port)
134+
prompt = "login" if force else None
135+
tokens = await oidc.authorization_code_grant(callback_port=callback_port, prompt=prompt)
128136

129137
config.token = tokens["access_token"]
130138

@@ -138,10 +146,11 @@ async def login( # noqa: C901
138146
case "exporter_config":
139147
ExporterConfigV1Alpha1.save(config, value) # ty: ignore[invalid-argument-type]
140148

149+
141150
@blocking
142151
async def relogin_client(config: ClientConfigV1Alpha1):
143152
"""Relogin into a jumpstarter instance"""
144-
client_id = "jumpstarter-cli" # TODO: store this metadata in the config
153+
client_id = "jumpstarter-cli" # TODO: store this metadata in the config
145154
try:
146155
issuer = decode_jwt_issuer(config.token)
147156
except Exception as e:
@@ -151,7 +160,6 @@ async def relogin_client(config: ClientConfigV1Alpha1):
151160
oidc = Config(issuer=issuer, client_id=client_id)
152161
tokens = await oidc.authorization_code_grant()
153162
config.token = tokens["access_token"]
154-
ClientConfigV1Alpha1.save(config) # ty: ignore[invalid-argument-type]
163+
ClientConfigV1Alpha1.save(config) # ty: ignore[invalid-argument-type]
155164
except Exception as e:
156165
raise ReauthenticationFailed(f"Failed to re-authenticate: {e}") from e
157-

0 commit comments

Comments
 (0)