---
title: How to Sign In with Azure Entra ID Using Capacitor
description: Learn how to integrate Microsoft Entra ID authentication into your Capacitor app using the OAuth plugin with PKCE on Android, iOS, and web.
date:
  created: 2026-02-12
  updated: 2026-07-14
authors:
  - robingenz
categories:
  - Capacitor
  - Guides
  - SDKs
links:
  - Capacitor OAuth: sdks/capacitor/oauth.md
faq: true
---

# How to Sign In with Azure Entra ID Using Capacitor

Many enterprise applications rely on [Microsoft Entra ID](https://www.microsoft.com/en-us/security/business/identity-access/microsoft-entra-id){:target="_blank"} (formerly Azure Active Directory) for identity and access management. If you're building a cross-platform app with Capacitor, the [Capacitor OAuth plugin](../../sdks/capacitor/oauth.md) makes it straightforward to integrate Entra ID authentication using the Authorization Code flow with PKCE. This guide walks you through app registration, sign-in, token management, and accessing the Microsoft Graph API.

<!-- more -->

<div class="capawesome-z29o10a">
  <a href="/" target="_blank">
    <img alt="Build and deploy your Capacitor app with Capawesome Cloud" src="https://capawesome.io/assets/banners/cloud-build-and-deploy-capacitor-apps.png?t=1" />
  </a>
</div>

## Bonus: Video Tutorial and Demo App

This walkthrough explains the OAuth plugin flow end-to-end in Capacitor, including PKCE, callback handling, and secure token usage patterns. You can apply the same implementation approach to Microsoft Entra ID by using your Entra issuer and client setup.

<div style="margin-top: 2rem;">
  <iframe
    width="100%"
    height="450px"
    src="https://www.youtube-nocookie.com/embed/Cr1dJNN6Urw?rel=0&modestbranding=1"
    frameborder="0"
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
    referrerpolicy="strict-origin-when-cross-origin"
    allowfullscreen
  ></iframe>
</div>

- **[OAuth Demo App](https://github.com/capawesome-team/capacitor-oauth-demo){:target="_blank"}** — A reusable Capacitor OAuth reference app that you can adapt for Entra ID provider settings.

## Prerequisites

Before you begin, make sure you have the following:

- A **Microsoft Entra ID tenant**. If you don't have one, you can [create a free Azure account](https://azure.microsoft.com/en-us/free/){:target="_blank"}.
- A **Capacitor app** with the [Capacitor OAuth plugin](../../sdks/capacitor/oauth.md) installed. To install the plugin, please refer to the [Installation](../../sdks/capacitor/oauth.md/#installation) section in the plugin documentation.

## Setting Up Azure Entra ID

### Registering Your App

First, you need to register your application in the Microsoft Entra admin center:

1. Sign in to the [Microsoft Entra admin center](https://entra.microsoft.com/){:target="_blank"}.
2. Navigate to **Entra ID** > **App registrations** > **New registration**.
3. Enter a **Name** for your application (e.g. `My Capacitor App`).
4. Under **Supported account types**, select the option that fits your use case:
    - **Single tenant**: Only accounts in your directory.
    - **Multitenant**: Accounts in any organizational directory.
    - **Multitenant + personal**: Includes Microsoft personal accounts.
5. Under **Redirect URI**, select the platform and enter a redirect URI (see [Configuring Redirect URIs](#configuring-redirect-uris) below).
6. Click **Register**.
7. On the app overview page, note the **Application (client) ID** and **Directory (tenant) ID**. You will need these later.

### Configuring Redirect URIs

You need to register a redirect URI for each platform you want to support. To add multiple redirect URIs, go to **Overview** > **Redirect URIs** and click **Add Redirect URI**.

**Android and iOS**: Select **Public client/native (mobile & desktop)** and use a custom scheme based on your app's package name or bundle identifier:

```
com.example.app://oauth/callback
```

**Web**: Select **Single-page application (SPA)** and use your web app's URL:

```
http://localhost:3000/oauth/callback
```

## Implementing Authentication

Throughout the following examples, replace `{tenant-id}` with your **Directory (tenant) ID** and `{client-id}` with your **Application (client) ID**.

### Signing In

Use the [`login(...)`](../../sdks/capacitor/oauth.md#login) method to start the OAuth flow. The plugin automatically fetches the OpenID Connect discovery document from the issuer URL and handles the PKCE exchange:

```typescript
import { Oauth } from '@capawesome-team/capacitor-oauth';

const login = async () => {
  const result = await Oauth.login({
    issuerUrl: 'https://login.microsoftonline.com/{tenant-id}/v2.0',
    clientId: '{client-id}',
    redirectUrl: 'com.example.app://oauth/callback',
    scopes: ['openid', 'profile', 'email', 'offline_access'],
  });
  console.log('Access token:', result.accessToken);
  console.log('ID token:', result.idToken);
  console.log('Refresh token:', result.refreshToken);
};
```

Include the `offline_access` scope to receive a refresh token.

### Handling the Redirect Callback (Web)

On the web, the [`login(...)`](../../sdks/capacitor/oauth.md#login) method redirects the user to the Microsoft login page. After authentication, the user is redirected back to your app. You need to call [`handleRedirectCallback()`](../../sdks/capacitor/oauth.md#handleredirectcallback) on page load to complete the token exchange:

```typescript
import { Oauth } from '@capawesome-team/capacitor-oauth';
import { Capacitor } from '@capacitor/core';

const handleRedirectCallback = async () => {
  if (Capacitor.getPlatform() !== 'web') {
    return;
  }
  const url = new URL(window.location.href);
  if (!url.searchParams.has('code')) {
    return;
  }
  const result = await Oauth.handleRedirectCallback();
  console.log('Access token:', result.accessToken);
};

handleRedirectCallback();
```

This step is only required on the web. On Android and iOS, the redirect is handled natively.

### Refreshing the Access Token

Access tokens expire after a short time. Use the [`refreshToken(...)`](../../sdks/capacitor/oauth.md#refreshtoken) method to get a new access token without requiring the user to sign in again:

```typescript
import { Oauth } from '@capawesome-team/capacitor-oauth';

const refreshToken = async () => {
  const result = await Oauth.refreshToken({
    issuerUrl: 'https://login.microsoftonline.com/{tenant-id}/v2.0',
    clientId: '{client-id}',
    refreshToken: 'YOUR_REFRESH_TOKEN',
  });
  console.log('New access token:', result.accessToken);
};
```

### Decoding the ID Token

Use the [`decodeIdToken(...)`](../../sdks/capacitor/oauth.md#decodeidtoken) method to read the user's profile claims from the ID token:

```typescript
import { Oauth } from '@capawesome-team/capacitor-oauth';

const decodeIdToken = async () => {
  const result = await Oauth.decodeIdToken({
    token: 'YOUR_ID_TOKEN',
  });
  console.log('Name:', result.payload.name);
  console.log('Email:', result.payload.preferred_username);
};
```

This decodes the JWT locally without sending it to a server. For server-side validation, you should verify the token on your backend.

### Signing Out

End the session with the [`logout(...)`](../../sdks/capacitor/oauth.md#logout) method:

```typescript
import { Oauth } from '@capawesome-team/capacitor-oauth';

const logout = async () => {
  await Oauth.logout({
    issuerUrl: 'https://login.microsoftonline.com/{tenant-id}/v2.0',
    idToken: 'YOUR_ID_TOKEN',
    postLogoutRedirectUrl: 'com.example.app://oauth/logout',
  });
};
```

Note that Microsoft Entra ID may show a "You have signed out" page instead of redirecting back to your app. In this case, the user needs to close the browser manually, which results in a `USER_CANCELED` error even though the logout was successful.

## Accessing the Microsoft Graph API

To call the [Microsoft Graph API](https://learn.microsoft.com/en-us/graph/overview){:target="_blank"}, request the `User.Read` scope (or other scopes you need) during login and use the access token in your requests:

```typescript
import { Oauth } from '@capawesome-team/capacitor-oauth';

const login = async () => {
  const result = await Oauth.login({
    issuerUrl: 'https://login.microsoftonline.com/{tenant-id}/v2.0',
    clientId: '{client-id}',
    redirectUrl: 'com.example.app://oauth/callback',
    scopes: ['openid', 'profile', 'email', 'offline_access', 'User.Read'],
  });

  const response = await fetch('https://graph.microsoft.com/v1.0/me', {
    headers: {
      Authorization: `Bearer ${result.accessToken}`,
    },
  });
  const user = await response.json();
  console.log('Display name:', user.displayName);
  console.log('Email:', user.mail);
};
```

## Enforcing App Protection Policies

Entra ID handles who can sign in, but enterprises often also need to control what happens to corporate data once the user is inside the app — preventing copy-paste to personal apps, requiring a PIN, or wiping company data on demand. These Mobile Application Management (MAM) rules are configured in Microsoft Intune. If your app targets managed enterprise devices, the [Capacitor Intune plugin](../../sdks/capacitor/intune.md) integrates the Microsoft Intune App SDK to enforce app protection policies on Android and iOS, complementing the Entra ID sign-in flow above.

## FAQ

### Which platforms does this work on?

The [Capacitor OAuth plugin](../../sdks/capacitor/oauth.md) runs the Authorization Code flow with PKCE on Android, iOS, and the web from a single codebase. On Android and iOS the flow completes natively; on the web you finish it by calling [`handleRedirectCallback()`](../../sdks/capacitor/oauth.md#handleredirectcallback) on page load.

### Do I need a client secret to sign in with Entra ID?

No. You register a **public client** and authenticate with PKCE, so there is no client secret embedded in your app. Configure the mobile and web redirect URIs on your app registration and you're set.

### Can I sign in users from any Entra tenant?

That depends on the **supported account types** you choose when registering the app — single-tenant, multi-tenant, or multi-tenant plus personal Microsoft accounts. The issuer URL you pass to [`login(...)`](../../sdks/capacitor/oauth.md#login) reflects that choice (for example, a specific tenant ID versus the `common` or `organizations` endpoint).

### How do I call the Microsoft Graph API after signing in?

Request the Graph scopes you need (such as `User.Read`) during login and send the returned access token as a bearer token. See [Accessing the Microsoft Graph API](#accessing-the-microsoft-graph-api) for a complete example.

### Can I use the same approach for other identity providers?

Yes. The plugin speaks standard OpenID Connect, so the same flow works with [Auth0](./how-to-sign-in-with-auth0-using-capacitor.md), [Okta](./how-to-sign-in-with-okta-using-capacitor.md), or any compliant provider. For provider-specific SDKs, see [Google Sign-In](./how-to-sign-in-with-google-using-capacitor.md) and [Apple Sign-In](./how-to-sign-in-with-apple-using-capacitor.md).

## Related Posts

- [Alternative to the Ionic Auth Connect Plugin](./alternative-to-ionic-auth-connect-plugin.md)
- [Announcing the Capacitor OAuth Plugin](./announcing-the-capacitor-oauth-plugin.md)
- [How to Sign In with Apple Using Capacitor](./how-to-sign-in-with-apple-using-capacitor.md)
- [How to Sign In with Auth0 Using Capacitor](./how-to-sign-in-with-auth0-using-capacitor.md)

## Conclusion

In this guide, we covered how to set up Microsoft Entra ID authentication in a Capacitor app using the [Capacitor OAuth plugin](../../sdks/capacitor/oauth.md). From app registration and redirect URI configuration to sign-in, token refresh, and Microsoft Graph API access, the plugin handles the complexity of the OAuth flow so you can focus on building your application.

Explore the complete [API Reference](../../sdks/capacitor/oauth.md#api) to see all available methods and options. If you're using Okta instead, check out [How to Sign In with Okta Using Capacitor](./how-to-sign-in-with-okta-using-capacitor.md). Have suggestions or questions? [Create an issue](https://github.com/capawesome-team/capacitor-plugins/issues/new/choose){:target="_blank"} in our [GitHub repository](https://github.com/capawesome-team/capacitor-plugins){:target="_blank"}.

Stay connected with us on [X](https://x.com/capawesomeio){:target="_blank"} and subscribe to our [newsletter](/newsletter/){:target="_blank"} for the latest updates.
