capacitor-msal-broker
v1.0.0
Published
Capacitor plugin for MSAL authentication with broker support for Intune/Conditional Access
Maintainers
Readme
capacitor-msal-broker
A Capacitor plugin for Microsoft Authentication Library (MSAL) with broker support for iOS. This plugin enables authentication through Microsoft Authenticator app, which is required for Intune MDM/MAM and Conditional Access compliance.
Features
- ✅ Native MSAL authentication on iOS
- ✅ Broker authentication via Microsoft Authenticator
- ✅ Intune/Conditional Access compliance
- ✅ Single Sign-On (SSO) support
- ✅ Silent token acquisition
- ✅ Keychain sharing for SSO across apps
Requirements
- Capacitor 7.x
- iOS 14.0+
- Microsoft Authenticator app installed (for broker authentication)
Installation
npm install capacitor-msal-broker
npx cap sync iosiOS Setup
1. Configure URL Schemes in Info.plist
Add the following to your ios/App/App/Info.plist:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleURLSchemes</key>
<array>
<string>msauth.$(PRODUCT_BUNDLE_IDENTIFIER)</string>
</array>
</dict>
</array>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>msauthv2</string>
<string>msauthv3</string>
<string>msauth</string>
</array>2. Configure Keychain Sharing in Entitlements
Add the following to your ios/App/App/App.entitlements:
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)com.microsoft.adalcache</string>
</array>3. Azure Portal Configuration
In your Azure AD App Registration:
- Go to Authentication → Platform configurations → iOS/macOS
- Add your Bundle ID
- Configure the redirect URI:
msauth.<your-bundle-id>://auth
Usage
Initialize
import { MsalBroker } from 'capacitor-msal-broker';
await MsalBroker.initialize({
clientId: 'your-azure-client-id',
tenant: 'organizations', // or specific tenant ID
authorityUrl: 'https://login.microsoftonline.com/organizations',
scopes: ['User.Read', 'email'], // Don't include openid, profile, offline_access
redirectUri: 'msauth.com.your.bundleid://auth',
brokerEnabled: true,
keychainGroup: 'com.microsoft.adalcache',
});Important: Do not include
openid,profile, oroffline_accessin scopes - MSAL iOS adds these automatically.
Login (Interactive)
try {
const result = await MsalBroker.login();
console.log('Access Token:', result.accessToken);
console.log('User:', result.account.username);
} catch (error) {
console.error('Login failed:', error);
}Get Accounts
const { accounts } = await MsalBroker.getAccounts();
if (accounts.length > 0) {
console.log('Found account:', accounts[0].username);
}Acquire Token Silently
try {
const result = await MsalBroker.acquireTokenSilently({
identifier: account.identifier,
forceRefresh: false,
});
console.log('Token:', result.accessToken);
} catch (error) {
// Silent auth failed, use interactive login
const result = await MsalBroker.login();
}Logout
await MsalBroker.logout();API Reference
initialize(options: MsalBrokerInitOptions): Promise<{ success: boolean }>
Initialize MSAL with your configuration.
| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | clientId | string | Yes | Azure AD Application (client) ID | | tenant | string | No | Tenant ID or 'organizations'/'common' | | authorityUrl | string | No | Authority URL | | scopes | string[] | No | OAuth scopes to request | | redirectUri | string | No | Redirect URI configured in Azure | | brokerEnabled | boolean | No | Enable broker authentication (default: true) | | keychainGroup | string | No | Keychain group for SSO | | knownAuthorities | string[] | No | List of known authorities |
login(options?: MsalBrokerLoginOptions): Promise<MsalBrokerAuthResult>
Perform interactive login.
| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | loginHint | string | No | Pre-fill username | | prompt | string | No | Prompt behavior: 'selectAccount', 'login', 'consent', 'none' |
acquireTokenSilently(options: MsalBrokerSilentOptions): Promise<MsalBrokerAuthResult>
Acquire token silently for an existing account.
| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | identifier | string | Yes | Account identifier | | forceRefresh | boolean | No | Force token refresh |
getAccounts(): Promise<{ accounts: MsalBrokerAccount[] }>
Get all cached accounts.
logout(): Promise<{ success: boolean }>
Sign out and clear cached tokens.
Types
interface MsalBrokerAuthResult {
accessToken: string;
idToken?: string;
expiresOn: string;
scopes: string[];
account: MsalBrokerAccount;
}
interface MsalBrokerAccount {
identifier: string;
username: string;
tenantId?: string;
name?: string;
}Troubleshooting
Error -50000: Reserved scopes
Remove openid, profile, and offline_access from your scopes array. MSAL iOS adds these automatically.
Error -51112: Broker not responding
- Ensure Microsoft Authenticator is installed
- Verify your redirect URI matches Azure Portal configuration
- Check that keychain sharing is properly configured
Keychain errors (-25300)
Ensure your entitlements include the correct keychain access groups with $(AppIdentifierPrefix) prefix.
License
MIT
