Skip to content

Commit 3e32629

Browse files
author
Shira Sassoon
committed
Merge branch 'feature/azure-cli-auth-poc' of https://github.com/shirasassoon/fabric-cli into feature/azure-cli-auth-poc
2 parents 769b0cf + 3ff1e13 commit 3e32629

3 files changed

Lines changed: 69 additions & 50 deletions

File tree

src/fabric_cli/commands/auth/fab_auth.py

Lines changed: 62 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -226,55 +226,68 @@ def logout(args: Namespace) -> None:
226226
def status(args: Namespace) -> None:
227227
auth = FabAuth()
228228
tenant_id = auth.get_tenant_id()
229+
identity_type = auth.get_identity_type() or "N/A"
229230

230-
def __get_token_info(scope):
231-
try:
232-
token = auth.get_access_token(scope, interactive_renew=False)
233-
except FabricCLIError as e:
234-
if e.status_code in [
235-
fab_constant.ERROR_UNAUTHORIZED,
236-
fab_constant.ERROR_AUTHENTICATION_FAILED,
237-
]:
238-
return {}
239-
else:
240-
raise e
241-
if isinstance(token, str):
242-
token = token.encode() # Ensure bytes type
243-
return _get_token_info_from_bearer_token(token) if token else {}
244-
245-
token_info = __get_token_info(fab_constant.SCOPE_FABRIC_DEFAULT)
246-
247-
upn = token_info.get("upn") or "N/A"
248-
oid = token_info.get("oid") or "N/A"
249-
tid = token_info.get("tid", tenant_id) or "N/A"
250-
appid = token_info.get("appid") or "N/A"
251-
252-
def __mask_token(scope):
253-
try:
254-
token = auth.get_access_token(scope, interactive_renew=False)
255-
except FabricCLIError as e:
256-
if e.status_code in [
257-
fab_constant.ERROR_UNAUTHORIZED,
258-
fab_constant.ERROR_AUTHENTICATION_FAILED,
259-
]:
260-
return "N/A"
261-
else:
262-
raise e
263-
if isinstance(token, str):
264-
token = token.encode() # Ensure bytes type
265-
return (
266-
token[:4].decode() + "************************************"
267-
if token
268-
else "N/A"
269-
)
231+
# Suppress noisy Azure SDK stderr logging during status checks
232+
# (AzureCliCredential logs "Please run 'az login'" before raising)
233+
import logging
234+
235+
azure_logger = logging.getLogger("azure.identity")
236+
original_level = azure_logger.level
237+
azure_logger.setLevel(logging.CRITICAL)
238+
239+
try:
240+
241+
def __get_token_info(scope):
242+
try:
243+
token = auth.get_access_token(scope, interactive_renew=False)
244+
except FabricCLIError as e:
245+
if e.status_code in [
246+
fab_constant.ERROR_UNAUTHORIZED,
247+
fab_constant.ERROR_AUTHENTICATION_FAILED,
248+
]:
249+
return {}
250+
else:
251+
raise e
252+
if isinstance(token, str):
253+
token = token.encode() # Ensure bytes type
254+
return _get_token_info_from_bearer_token(token) if token else {}
255+
256+
token_info = __get_token_info(fab_constant.SCOPE_FABRIC_DEFAULT)
257+
258+
upn = token_info.get("upn") or "N/A"
259+
oid = token_info.get("oid") or "N/A"
260+
tid = token_info.get("tid", tenant_id) or "N/A"
261+
appid = token_info.get("appid") or "N/A"
262+
263+
def __mask_token(scope):
264+
try:
265+
token = auth.get_access_token(scope, interactive_renew=False)
266+
except FabricCLIError as e:
267+
if e.status_code in [
268+
fab_constant.ERROR_UNAUTHORIZED,
269+
fab_constant.ERROR_AUTHENTICATION_FAILED,
270+
]:
271+
return "N/A"
272+
else:
273+
raise e
274+
if isinstance(token, str):
275+
token = token.encode() # Ensure bytes type
276+
return (
277+
token[:4].decode() + "************************************"
278+
if token
279+
else "N/A"
280+
)
281+
282+
fabric_secret = __mask_token(fab_constant.SCOPE_FABRIC_DEFAULT)
283+
storage_secret = __mask_token(fab_constant.SCOPE_ONELAKE_DEFAULT)
284+
azure_secret = __mask_token(fab_constant.SCOPE_AZURE_DEFAULT)
270285

271-
fabric_secret = __mask_token(fab_constant.SCOPE_FABRIC_DEFAULT)
272-
storage_secret = __mask_token(fab_constant.SCOPE_ONELAKE_DEFAULT)
273-
azure_secret = __mask_token(fab_constant.SCOPE_AZURE_DEFAULT)
286+
finally:
287+
azure_logger.setLevel(original_level)
274288

275289
# Check login status
276290
is_logged_in = fabric_secret != "N/A"
277-
identity_type = auth.get_identity_type() or "N/A"
278291
login_status = (
279292
"✓ Logged in to app.fabric.microsoft.com"
280293
if is_logged_in
@@ -283,6 +296,11 @@ def __mask_token(scope):
283296
fab_ui.print_grey(login_status)
284297
if identity_type == "azure_cli" and is_logged_in:
285298
fab_ui.print_grey(f" Auth mode: Azure CLI (tenant: {tid})")
299+
elif identity_type == "azure_cli" and not is_logged_in:
300+
fab_ui.print_grey(
301+
" Azure CLI session expired or logged out. "
302+
"Run 'az login' then 'fab auth login --azure-cli' to re-authenticate."
303+
)
286304

287305
auth_data = {
288306
"logged_in": is_logged_in,

src/fabric_cli/core/fab_auth.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import json
55
import os
66
import base64
7+
import binascii
78
import uuid
89
from binascii import hexlify
910
from typing import Any, NamedTuple, Optional
@@ -491,12 +492,12 @@ def _decode_jwt_claims(token: str) -> dict:
491492
parts = token.split(".")
492493
if len(parts) < 2:
493494
return {}
494-
# Add padding for base64url decoding
495+
# Add padding for base64url decoding (avoid adding 4 when already aligned)
495496
payload = parts[1]
496-
payload += "=" * (4 - len(payload) % 4)
497+
payload += "=" * ((-len(payload)) % 4)
497498
decoded = base64.urlsafe_b64decode(payload)
498499
return json.loads(decoded)
499-
except (ValueError, json.JSONDecodeError, UnicodeDecodeError):
500+
except (ValueError, json.JSONDecodeError, UnicodeDecodeError, binascii.Error):
500501
return {}
501502

502503
def _acquire_token_from_azure_cli(self, scope: list[str]) -> dict:

tests/test_commands/test_auth.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -966,7 +966,7 @@ def test_init_with_azure_cli_flag(self, mock_fab_auth, mock_fab_context):
966966
mock_fab_auth_instance.set_access_mode.assert_called_with(
967967
"azure_cli", None
968968
)
969-
mock_set_azure_cli.assert_called_once_with(None)
969+
mock_set_azure_cli.assert_called_once_with(tenant_id=None)
970970
assert result is True
971971

972972
def test_init_with_azure_cli_flag_and_tenant(
@@ -985,7 +985,7 @@ def test_init_with_azure_cli_flag_and_tenant(
985985
mock_fab_auth_instance.set_access_mode.assert_called_with(
986986
"azure_cli", "my-tenant"
987987
)
988-
mock_set_azure_cli.assert_called_once_with("my-tenant")
988+
mock_set_azure_cli.assert_called_once_with(tenant_id="my-tenant")
989989
assert result is True
990990

991991
def test_init_with_interactive_azure_cli_selection(
@@ -1008,7 +1008,7 @@ def test_init_with_interactive_azure_cli_selection(
10081008
mock_fab_auth_instance.set_access_mode.assert_called_with(
10091009
"azure_cli", None
10101010
)
1011-
mock_set_azure_cli.assert_called_once_with(None)
1011+
mock_set_azure_cli.assert_called_once_with(tenant_id=None)
10121012
assert_get_access_token(mock_fab_auth_instance)
10131013
assert_fab_context(mock_fab_context)
10141014
assert result is True

0 commit comments

Comments
 (0)