[Bug] macOS broker prompts twice for Keychain access, Always Allow doesn't apply to both
Dieses Issue hat noch niemand übernommen.
Bewertung
- Schwierigkeit
- 5/5
- Geschätzter Aufwand
- Über eine Woche
- Anfängerfreundlichkeit
- 25/100
- Issue-Typ
- Bug
- Klarheit
- Klar beschrieben
- Aktivitätsstatus
- Ruhig
- Tech-Stack
- macos, python
- Bereich
- authentication, security
Rechercherichtung
The report points to Common Core’s MSIDMacKeychainTokenCache.m and MSIDMacACLKeychainAccessor.m, and asks about PyMsalRuntime’s unsigned-client flow. Start by tracing how one broker response is written to the shared and non-shared Keychain items, then check whether the Python repository exposes that flow. Done means establishing a supported way to avoid duplicate authorization prompts while preserving the shared/non-shared credential boundary.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
Describe the bug
On macOS, one broker-backed MSAL operation can (frequently) display two consecutive Keychain password dialogs. Choosing Always Allow in the first dialog does not prevent the second dialog. After choosing Always Allow in both dialogs, later requests stop prompting until the interpreter identity or Keychain state changes.
I had copilot confirm that my app makes one msal.broker._signin_silently() call and that MSAL makes one native pymsalruntime.signin_silently() call. The dialogs therefore arise within one native broker operation rather than from duplicate application authentication. It feels wrong to have to type my password twice for a single operation.
To reproduce
Prerequisites:
- macOS with Company Portal and broker support configured.
- A public client registration configured for the macOS broker.
- An account already available to the broker.
- An ad-hoc-signed Python executable that is not already trusted by the relevant login-Keychain items.
import msal
CLIENT_ID = "<public-client-id>"
AUTHORITY = "https://login.microsoftonline.com/<tenant>"
SCOPES = ["<scope>"]
app = msal.PublicClientApplication(
client_id=CLIENT_ID,
authority=AUTHORITY,
enable_broker_on_mac=True,
)
# With prompt omitted, the broker path first attempts one silent sign-in.
result = app.acquire_token_interactive(scopes=SCOPES)
print(result.get("error") or "Token acquired")
Run the script with the ad-hoc-signed interpreter. When its executable has not previously been authorized for the existing MSAL Keychain cache, two Keychain dialogs will appear during the single silent broker operation.
Expected behavior
A single broker operation should not require two indistinguishable Keychain authorization grants. Ideally, an unsigned runtime-like broker client would rely on broker-owned persistent caching and use only process-local application caching. If persistent application-side Keychain caching is required, the UX should avoid or clearly explain multiple independent grants without weakening the shared/non-shared credential boundary.
What you see instead
- macOS requests the login-Keychain password.
- Always Allow is selected.
- A second, apparently identical Keychain password dialog immediately appears.
- Always Allow is selected again.
- Subsequent runs remain silent for a period of time.
The MSAL Python version you are using
msal==1.38.0
pymsalruntime==0.20.6
MSAL Python 1.38.0 already contains the unsigned-app redirect URI change from #907.
Environment
- macOS 26.6.2
- Apple Silicon (
arm64) - Company Portal 5.2606.0
- CPython 3.11.12 installed by uv
- Python signature: ad-hoc/linker-signed
TeamIdentifier=not set
Investigation
Non-PII native logging showed:
- The runtime continuing through the unsigned-app runtime flow.
- Shared Keychain-group operations failing with
-34018(errSecMissingEntitlement), as expected for an ad-hoc-signed Python executable without the shared Keychain entitlement. - A fallback to the ACL-based login-Keychain implementation.
- Multiple successful reads and updates through the macOS ACL Keychain accessor during the one silent sign-in.
The Common Core implementation appears to explain why two grants are needed:
MSIDMacKeychainTokenCache.mstores two distinct generic-password items:- A shared blob containing refresh tokens and accounts.
- A non-shared blob containing access tokens, ID tokens, app metadata, and account metadata.
- Both use the service/ACL label
Microsoft Credentials, but they have different Keychain primary keys and independent ACLs. MSIDMacACLKeychainAccessor.mcreates a trusted-application reference for the current executable and reads each item withSecItemCopyMatching.
This is consistent with the observed behavior: Always Allow updates authorization for one Keychain item, but the other item still needs a separate grant even though the dialogs look the same. A changed Python installation path or executable identity can require new grants.
Upstream question
For unsigned runtime-like clients using the macOS broker, can PyMsalRuntime/Common Core avoid writing the broker response to the legacy ACL-based login-Keychain token cache and instead rely on broker persistence plus an in-memory process cache?
If the local cache is required for account discovery or other semantics, is there another way to avoid two separate user authorization dialogs while retaining the intentional shared/non-shared security boundary?
No tenant IDs, client IDs, account identifiers, correlation IDs, or token material are included in this report.
- Vorherrschende Sprache
- Python
- Sterne
- 971
- Forks
- 223
- Ø Merge
- 1 T. 32 Min.
- Gemergte PRs (30 T.)
- 1
Entwicklungsumgebung
- Kein Dockerfile und keine Docker-Compose-Datei
- Keine Pull-Request-Vorlage
- Beitragsleitfaden lesen
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus AzureAD/microsoft-authentication-library-for-python
-
needs attention untriaged
Schwierigkeit 4/5 3-5 Tage Anfängerfreundlichkeit 48/100
AzureAD/microsoft-authentication-library-for-python#973 · 3 Kommentare ·
-
AzureSDK bug P1
Schwierigkeit 4/5 3-5 Tage Anfängerfreundlichkeit 48/100
-
http_client docstring does not say that timeout, verify and proxies only configure the default sessionEvtl. vergeben @HardMax71 hat das vor 47 Tagen übernommen. Offen
Schwierigkeit 1/5 Unter einer Stunde Anfängerfreundlichkeit 25/100
-
[Bug] The built-in retry never retries the token POST: HTTPAdapter(max_retries=1) keeps urllib3's default allowed_methodsEvtl. vergeben @HardMax71 hat das vor 53 Tagen übernommen. Offenbug untriaged
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 35/100
AzureAD/microsoft-authentication-library-for-python#957 · 3 Kommentare ·
-
[Bug] Interactive auth callback hangs forever when an idle connection reaches AuthCodeReceiver firstEvtl. vergeben @Thanatos9404 hat das vor 12 Tagen übernommen. Offenbug public-client
Schwierigkeit 4/5 1-2 Tage Anfängerfreundlichkeit 48/100
AzureAD/microsoft-authentication-library-for-python#950 · 2 Kommentare · 3 Reaktionen ·
Alle Issues in AzureAD/microsoft-authentication-library-for-python
Ähnliche Issues
-
component:benchmark
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 76/100
agentic-os-org/ANOLISA#9177 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 1/5 Unter einer Stunde Anfängerfreundlichkeit 88/100
distrochooser/distrochooser#520 ·
Maintainer antworten meist innerhalb von 2 Tagen
-
Status: Needs confirmation Status: Needs triage
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 64/100
Maintainer antworten meist innerhalb von 1 Tag
-
[BUG] Published Docker images lack the redis extra: HEADROOM_COMPRESS_SESSION_STORE stops startupEvtl. vergeben @AlessandroSpallina hat das heute übernommen. Offen
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 76/100
headroomlabs-ai/headroom#4513 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 1/5 Unter einer Stunde Anfängerfreundlichkeit 65/100
codespell-project/codespell#4060 ·
Maintainer antworten meist innerhalb von 1 Tag