Aller directement au contenu principal

Se connecter avec Microsoft Entra ID (Azure AD) dans Capacitor

Ajouter la connexion Microsoft Entra ID (Azure AD) à une Capacitor 8 application avec PKCE : inscription de l'application, URIs de redirection, Graph et API autorisations, et corrections d'erreurs AADSTS.

Crédits de l'article

Martin Donadieu

Auteur

Valeria

Relecteur

Jordan

Éditeur

Se connecter avec Microsoft Entra ID (Azure AD) dans Capacitor

Pour vous connecter avec Microsoft Entra ID (anciennement Azure Active Directory) dans une Capacitor application, inscrivez-vous pour un client public dans le centre d'administration Entra, ajoutez un Applications mobiles et de bureau URI de redirection tel que com.example.app://oauth/azure, et exécutez le flux d'autorisation OpenID Connect code avec PKCE à travers le navigateur système. @capgo/capacitor-social-login ce qui signifie une initialize appeler avec les points de terminaison de la plateforme d'identité Microsoft v2.0 SocialLogin.login({ provider: 'oauth2', options: { providerId: 'azure' } }).

Cette guide couvre l'enregistrement de l'application, la sélection de l'autorité appropriée, le Graph et les champs de portée personnalisés API, la validation des jetons, l'accès conditionnel, la déconnexion et les erreurs AADSTS que vous verrez. Il s'adresse Capacitor 8 en octobre 2026.

Ce dont vous avez besoin

  • Un locataire Microsoft Entra et un rôle qui peut créer des enregistrements d'application (développeur d'application ou supérieur).
  • Une application Capacitor 8 et ses appId, que vous reutiliserez comme schéma de redirection.
  • Optionnellement, un backend API qui doit accepter les jetons Entra.

Pourquoi pas utiliser MSAL.js dans la vue WebView ?

MSAL.js est conçu pour les navigateurs qui possèdent leur origine et peuvent ouvrir des pop-ups. Dans une vue WebView Capacitor, l'origine est capacitor://localhost sur iOS et https://localhost sur Android, les pop-ups sont bloqués, et un redirigeant de page complète ferait dériver votre application loin de son propre bundle. La guidance de Microsoft pour les applications natives est le navigateur système avec PKCE (RFC 8252), ce que fait le plugin :

Plateforme Navigateur utilisé Extra setup
iOS ASWebAuthenticationSession Aucune
Android Chrome Custom Tabs avec androidUseCustomTabs: true Filtre d'intention
Web Pop-up ou redirige URI de redirection SPA

On Android, activez les onglets personnalisés. La vue Web intégrée par défaut ne peut pas communiquer avec Microsoft Authenticator, les mots de passe ou le portail de l'entreprise, sur lesquels l'accès conditionnel repose souvent.

Étape 1 : Enregistrer l'application dans Entra ID

  1. Ouvrez Centre d'administration d'Entra Microsoft et allez à Entra ID > Inscriptions d'applications > Nouvelle inscription.
  2. Entrez un nom, tel que « Exemple Mobile ».
  3. Sélectionnez Types de comptes pris en charge. Cela décide de l'autorité que vous utiliserez ensuite.
  4. Cliquez pour passer à l'étape suivante Inscrivez-vous.
  5. On Vue d'ensemble, copiez ID d'application (client) et ID de répertoire (locataire).

Sélectionnez l'autorité

Type de compte lors de l'inscription Ségment d'autorité dans les URL
Locataire unique (seulement votre entreprise) Votre ID de locataire, par exemple 8f1c...
Tout répertoire organisationnel organizations
Tout répertoire d'entreprise plus les comptes Microsoft personnels common
Seuls les comptes Microsoft personnels consumers

Utilisez l'ID de locataire chaque fois que possible. Il produit des émetteurs prévisibles et évite les connexions accidentelles provenant d'autres locataires.

Ajoutez les URIs de redirection

Allez à Authentification > Ajoutez une plateforme:

  • Applications mobiles et de bureau: ajoutez com.example.app://oauth/azure comme une URI de redirection personnalisée. Ajoutez com.example.app://oauth/logout si vous souhaitez une redirection après déconnexion.
  • Application unique en page (seulement si vous envoyez une build web) : ajoutez https://app.example.com/auth/callback.

Ne vous inscrivez pas l'URI mobile sous Web. Les plateformes web redirigent des clients confidentiels et nécessitent un secret à l'endpoint de jeton.

Les autorisations API

Les autorisations API contient déjà Microsoft Graph > User.Read. Ajoutez offline_access, openid, profile et email if they are not listed. Some tenants block user consent. In that case an admin must click Accordez le consentement administrateur, sinon les utilisateurs voient AADSTS65001 ou un écran "Besoin d'approbation administrative".

Exposez un champ d'accès pour votre propre API (facultatif)

Si votre serveur backend doit accepter le jeton :

  1. Ouvrir Exposez un API et définissez l'ID d'application URI, généralement api://<client-id>.
  2. Ajoutez un champ nommé access_as_user, who can consent: Admins and users.
  3. Dans Dans le fichier, définissez "requestedAccessTokenVersion": 2 afin que les jetons d'accès utilisent la forme d'émetteur v2.0.

Étape 2 : Installez le plugin et ajoutez le filtre d'intention

bun add @capgo/capacitor-social-login
bunx cap sync

In android/app/src/main/AndroidManifest.xml, à l'intérieur MainActivity:

<intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="com.example.app" android:host="oauth" />
</intent-filter>

Maintenez android:launchMode="singleTask" sur MainActivity (la valeur par défaut de Capacitor. Si vous ne utilisez pas Google, Apple ou Facebook pour vous connecter, désactivez-les sous plugins.SocialLogin.providers in capacitor.config.ts pour garder leurs SDKs hors de la construction.

Étape 3 : Initialiser le fournisseur Entra ID

import { Capacitor } from '@capacitor/core';
import { SocialLogin } from '@capgo/capacitor-social-login';

const TENANT = 'YOUR_TENANT_ID'; // or organizations / common
const AUTHORITY = `https://login.microsoftonline.com/${TENANT}/oauth2/v2.0`;
const isWeb = Capacitor.getPlatform() === 'web';

export async function initAuth() {
  await SocialLogin.initialize({
    oauth2: {
      azure: {
        appId: 'YOUR_CLIENT_ID',
        authorizationBaseUrl: `${AUTHORITY}/authorize`,
        accessTokenEndpoint: `${AUTHORITY}/token`,
        redirectUrl: isWeb
          ? 'https://app.example.com/auth/callback'
          : 'com.example.app://oauth/azure',
        scope: 'openid profile email offline_access User.Read',
        pkceEnabled: true,
        resourceUrl: 'https://graph.microsoft.com/v1.0/me',
        logoutUrl: `${AUTHORITY}/logout`,
        postLogoutRedirectUrl: isWeb ? 'https://app.example.com/' : 'com.example.app://oauth/logout',
        androidUseCustomTabs: true,
      },
    },
  });
}

context resourceUrl pointant vers le Graph /meAprès l'authentification, le plugin appelle directement Graph et renvoie le profil dans resourceData.

Si vous êtes en train de migrer depuis Ionic Auth Connect, SocialLoginAuthConnect possède une azure préconfiguration qui ne nécessite que tenantId, clientId et redirectUrl. Consultez la page d'intégration Entra ID.

Étape 4 : S'identifier

import { SocialLogin } from '@capgo/capacitor-social-login';

export async function signInWithMicrosoft() {
  try {
    const { result } = await SocialLogin.login({
      provider: 'oauth2',
      options: { providerId: 'azure' },
    });

    const me = result.resourceData as {
      id: string;
      displayName?: string;
      mail?: string | null;
      userPrincipalName?: string;
    } | null;

    return {
      idToken: result.idToken,
      graphToken: result.accessToken?.token,
      refreshToken: result.refreshToken,
      user: me,
    };
  } catch (error: any) {
    if (error?.code === 'USER_CANCELLED') return null;
    throw error;
  }
}

Options utiles :

  • loginHint: 'jane@contoso.com' remplit automatiquement le compte et saute le sélectionneur de compte pour cet utilisateur.
  • prompt: 'select_account' affiche toujours le sélectionneur de compte, utile pour les appareils partagés.
  • additionalParameters: { domain_hint: 'contoso.com' } envoie les utilisateurs directement vers leur identifiant fédéré.

mail est souvent null pour les comptes sans boîte aux lettres. Retourner à userPrincipalName ou le preferred_username revendication du jeton d'ID.

Étape 5 : Appelez Microsoft Graph

export async function getMyPhotoBlob(graphToken: string) {
  const res = await fetch('https://graph.microsoft.com/v1.0/me/photo/$value', {
    headers: { Authorization: `Bearer ${graphToken}` },
  });
  if (res.status === 404) return null; // no photo set
  if (!res.ok) throw new Error(`Graph error ${res.status}`);
  return res.blob();
}

Ajoutez chaque champ Graph dont vous avez besoin (par exemple Calendars.Read) les deux permissions d'API et dans le scope et dans la

Étape 6 : Obtenez un jeton pour votre propre API

Un jeton d'accès cible un seul ressource. Pour appeler votre backend, ajoutez une deuxième entrée à côté azure dans le même oauth2 carte de votre initialize appelez, en demandant votre API champ d'application au lieu de Graph :

await SocialLogin.initialize({
  oauth2: {
    azure: graphConfig, // the object from step 3, moved into a const
    azureApi: {
      appId: 'YOUR_CLIENT_ID',
      authorizationBaseUrl: `${AUTHORITY}/authorize`,
      accessTokenEndpoint: `${AUTHORITY}/token`,
      redirectUrl: 'com.example.app://oauth/azure-api', // register this URI too
      scope: 'openid profile offline_access api://YOUR_CLIENT_ID/access_as_user',
      pkceEnabled: true,
      androidUseCustomTabs: true,
    },
  },
});

L’utilisateur a déjà une session Microsoft, donc la deuxième connexion se termine généralement sans invitation. Validez le jeton sur le serveur :

import { createRemoteJWKSet, jwtVerify } from 'jose';

const TENANT_ID = 'YOUR_TENANT_ID';
const jwks = createRemoteJWKSet(
  new URL(`https://login.microsoftonline.com/${TENANT_ID}/discovery/v2.0/keys`),
);

export async function verifyEntraToken(token: string) {
  const { payload } = await jwtVerify(token, jwks, {
    issuer: `https://login.microsoftonline.com/${TENANT_ID}/v2.0`,
    audience: 'YOUR_CLIENT_ID', // v2 tokens use the client ID as aud
  });
  if (!String(payload.scp ?? '').split(' ').includes('access_as_user')) {
    throw new Error('Missing scope');
  }
  return payload; // payload.oid is the stable user object ID
}

Pour les applications multilocataires, l'émetteur contient l'ID de locataire de chaque client. Vérifiez que tid acceptez la liste des locataires au lieu d'un émetteur fixe. Les utilisateurs clés sur oid plus tidÉtape 7 : Raffraîchir et se déconnecter

Étape 7 : Raffraîchir et se déconnecter

// Get a valid Graph token, refreshing it when it has expired
export async function getGraphToken() {
  const { isLoggedIn } = await SocialLogin.isLoggedIn({ provider: 'oauth2', providerId: 'azure' });
  if (!isLoggedIn) {
    try {
      await SocialLogin.refresh({ provider: 'oauth2', options: { providerId: 'azure' } });
    } catch {
      // no session, or the refresh token expired or was revoked
      const loginResult = await signInWithMicrosoft();
      if (!loginResult) throw new Error('Sign-in cancelled');
    }
  }
  const { accessToken } = await SocialLogin.getAuthorizationCode({ provider: 'oauth2', providerId: 'azure' });
  return accessToken;
}

// Sign out
await SocialLogin.logout({ provider: 'oauth2', providerId: 'azure' });

Entra refresh tokens for public clients last up to 90 days with a sliding window and are replaced on each use. The plugin stores the new one. If you store tokens yourself, use the Keychain or Keystore, for example NativeBiometric.setData from @capgo/capacitor-native-biometriqueet les passez à SocialLogin.refreshToken.

logout clears local tokens and opens the v2.0 logout endpoint in the system browser. Microsoft sometimes shows a “You signed out of your account” page instead of redirecting to a custom scheme, so the user may have to close it. If you only need a local logout, drop logoutUrl et passer prompt: 'select_account' à l'entrée suivante.

Accès conditionnel et Intune

Le travail avec les politiques d'accès conditionnel et les authentifications à plusieurs facteurs nécessite une attention particulière.

  • Appareil conforme ou joint hybride: Entra doit voir l'état de l'appareil. Sur les appareils Android, cela fonctionne à travers les onglets personnalisés lorsque le Portail de l'entreprise ou l'Authentificateur est installé. Sur les appareils iOS gérés, le plug-in SSO d'entreprise Microsoft déployé par votre MDM fournit cela. Testez cela tôt avec une politique réelle.
  • Politiques de protection des applications Intune (MAM): ces exigent l'application Intune SDK à l'intérieur de l'application native. L’OIDC seul ne satisfait pas aux « exiger une politique de protection d'application ».

Troubleshooting

Error Erreur Fix
AADSTS50011 URI de redirection incohérent Ajoutez l'URI exacte sous Applications mobiles et desktop
AADSTS7000218 La demande de jeton nécessite un secret La redirection a été enregistrée sous Web. Déplacez-la sous Applications mobiles et desktop
AADSTS9002326 Seul le rachat de jetons d'origine autorisé pour les applications SPA La build Web utilise une redirection mobile. Enregistrez l'URL Web sous Application à page unique
AADSTS700016 L'application n'est pas trouvée dans le répertoire Erreur de locataire dans l'autorité, ou application mono-locataire utilisée avec common
AADSTS50020 Compte d'utilisateur provenant d'un autre locataire Utiliser une inscription multilocataire, ou inviter l'utilisateur en tant que invité
AADSTS65001 Consentement non accordé Grant admin consent or allow user consent
AADSTS53003 Bloqué par l'accès conditionnel Vérifier les journaux de connexion, voir la section ci-dessus
AADSTS28000 Étendues pour plus d'un ressource dans une seule demande Demander les graphiques et vos étendues API séparément dans des connexions
No token de rafraîchissement offline_access manquant Ajoutez-l’aux champs d'accès et aux autorisations

Le centre d'administration Entra Les journaux de connexion montrent la raison exacte d'échec pour chaque tentative, et logsEnabled: true dans la configuration du plugin, imprimez l'URL d'autorisation et la réponse de jeton sur le dispositif.

Actualités de livraison

Policy changes on the Entra side are instant, but client-side fixes still need to reach devices. TypeScript changes such as scopes or error handling can ship through Capgo mises à jour en directNative changes (intent filters, nouveaux schémas) nécessitent une nouvelle mise à jour de l'application, qui Capgo Construction peut produire sans un Mac local.

Mises à jour instantanées pour les applications Capacitor

When a web-layer bug is live, ship the fix through Capgo instead of waiting days for app store approval. Users get the update in the background while native changes stay in the normal review path.

Dernières actualités de notre Blog

Capgo vous offre les meilleures informations nécessaires pour créer une application mobile professionnelle.