Skip to content

iOS: knownAuthorities always set for AAD disables broker (Microsoft Authenticator), breaking Conditional Access #60

@ssyjoe

Description

@ssyjoe

Summary

On iOS, MsAuthPlugin.createContext always sets msalConfiguration.knownAuthorities = [authority] regardless of authorityType. For AAD authorities this marks the authority as pre-validated, which cascades into MSAL setting validateAuthority=false, which in turn causes shouldUseBroker to return false — the Microsoft Authenticator broker is silently bypassed for every AAD sign-in.

For tenants with a Conditional Access "require compliant/registered device" grant, this is a hard failure: sign-in reaches login.microsoftonline.com, the user enters credentials, and AAD blocks at the consent step with AADSTS530003: Device state: Unregistered. There's no client-side workaround other than patching this plugin.

Affected version

@recognizebv/capacitor-plugin-msauth@4.1.0 (iOS). Bug has been present since the AAD path was introduced.

Repro

  1. Configure any AAD tenant that has a CA policy requiring device registration.
  2. Install Microsoft Authenticator on a physical iOS device (broker installed).
  3. Call MsAuth.login({ authorityType: 'AAD', authorityUrl: 'https://login.microsoftonline.com/<tenant-id>', clientId, scopes, ... }).
  4. Expected: MSAL routes through Authenticator broker, device identity assertion is sent, sign-in completes.
  5. Actual: MSAL uses ASWebAuthenticationSession instead, device identity is not asserted, AAD returns AADSTS530003.

Root cause

ios/Plugin/Plugin.swift around L199:

let msalConfiguration = MSALPublicClientApplicationConfig(clientId: clientId, redirectUri: nil, authority: authority)
msalConfiguration.knownAuthorities = [authority]
return try MSALPublicClientApplication(configuration: msalConfiguration)

Per Microsoft's MSAL iOS documentation, `knownAuthorities` is for non-standard authorities (B2C/CIAM) that aren't on Microsoft's published trust list. It should not be set for AAD. Setting it for AAD marks the authority as pre-validated, which disables broker use.

Two secondary symptoms that confirm this is unintentional:

  1. The plugin already accepts `authorityType: 'AAD' | 'B2C' | 'CIAM'` — it knows the shape of the authority but doesn't use it here.
  2. The plugin accepts a `knownAuthorities` JS config field but the Swift side never reads it — that's a dead pass-through.

Proposed fix

Gate the assignment on `authorityType`:

let msalConfiguration = MSALPublicClientApplicationConfig(clientId: clientId, redirectUri: nil, authority: authority)
// knownAuthorities is for custom / non-AAD authorities. Setting it on AAD marks the
// authority as pre-validated and silently disables broker (Microsoft Authenticator)
// integration, breaking Conditional Access device-compliance policies.
if authorityType != .aad {
    msalConfiguration.knownAuthorities = [authority]
}
return try MSALPublicClientApplication(configuration: msalConfiguration)

Happy to open a PR if that'd be useful.

Workaround

`patch-package` the file above with the conditional. We've been running this fix in production against an Intune-managed tenant and it works correctly — broker is invoked on first login, device identity flows through, CA policy is satisfied, and subsequent silent refresh uses the MSAL keychain cache.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions