Skip to content
← Blog

Beyond SMS Codes: A Technical Guide to Entra ID Passkey Integration for Custom Apps

Implement entra id passkey integration to eliminate SMS phishing. Learn step-by-step how to secure your custom web and mobile apps with passkeys.

Beyond SMS Codes: A Technical Guide to Entra ID Passkey Integration for Custom Apps

The Security Crisis of Legacy Multi-Factor Authentication

A single SIM-swapping or SMS-intercept attack can bypass legacy multi-factor authentication (MFA) in under 10 minutes, exposing critical corporate databases to unauthorized access. Yet, security audits show that over 65% of European enterprises still rely on SMS codes or voice calls as their secondary authentication factor. This reliance creates a massive, highly vulnerable attack surface.

Microsoft is now forcing a decisive shift by making passkeys the default authentication method in Microsoft Entra ID. This update initiates the gradual phase-out of SMS and voice-based verification. For technical leaders and software architects, this is a technical mandate to update custom web, desktop, and mobile applications to support passwordless FIDO2 and WebAuthn protocols.

Implementing this transition requires a deep understanding of cryptographic authentication and modern web standards. If your applications are built with custom frontends that interface with Microsoft Entra ID, you must adapt your authentication layers to support native biometrics and hardware keys. This guide details why this shift is happening, how WebAuthn works under the hood, and how to execute an entra id passkey integration within your custom software stack.

For years, SMS-based MFA was considered a reasonable compromise between security and user convenience. However, modern attack vectors have rendered it obsolete. Threat actors now bypass SMS and time-based one-time passwords (TOTP) using real-time reverse proxy phishing kits like Evilginx. These kits act as a man-in-the-middle, transparently relaying login requests between the user and the actual identity provider.

The attacker intercepts not only the password and the MFA code but also the resulting session cookie. This allows them to hijack the authenticated session completely. Another critical vulnerability is SIM swapping, where an attacker social-engineers a mobile carrier into porting the victim's phone number to a new SIM card. Once completed, the attacker receives all SMS codes intended for the victim.

Furthermore, SMS and voice calls rely on the Signaling System No. 7 (SS7) telecommunications protocol. This protocol contains well-documented vulnerabilities allowing state-sponsored actors and sophisticated hackers to intercept text messages and calls over the air. In contrast, passkeys are built on the FIDO2 standard, which combines the W3C Web Authentication (WebAuthn) API and the Client-to-Authenticator Protocol (CTAP).

Passkeys utilize asymmetric public-key cryptography. During registration, the user’s device generates a unique cryptographic key pair. The private key is securely stored in the device's hardware enclave, such as a TPM chip or Apple's Secure Enclave. The public key is then sent to the identity provider.

Unlike passwords or OTPs, passkeys are cryptographically bound to the specific domain of the website or application. During login, the browser checks the domain origin before prompting the user for biometrics. If an employee is tricked into visiting a spoofed login page, the browser will recognize the mismatch and refuse to invoke the credentials. This mechanism reduces phishing-related credential theft rates from approximately 82% to virtually 0%.

The table below contrasts the security and operational characteristics of traditional MFA methods against passkeys:

| Feature | SMS / Voice MFA | App-Based OTP (TOTP) | Passkeys (FIDO2 / WebAuthn) | | :--- | :--- | :--- | :--- | | Phishing Resistance | None (easily bypassed via reverse proxies) | None (vulnerable to real-time proxies) | Cryptographically absolute (bound to domain origin) | | SIM Swapping Protection | Zero protection | High (not tied to carrier) | Absolute (private key never leaves hardware) | | User Onboarding Friction | Low (familiar to users) | Medium (requires installing authenticator app) | Low (uses native device biometrics, e.g., FaceID) | | Average Login Speed | ~18 seconds (waiting for SMS and typing) | ~12 seconds (switching apps, copying code) | ~2.5 seconds (single biometric scan) | | Regulatory Compliance | Deprecated / Disallowed for AAL3 | Allowed for AAL2 only | Required for Authenticator Assurance Level 3 (AAL3) |

Technical Anatomy of the WebAuthn Lifecycle

To successfully integrate passkeys, developers must understand the interaction between the relying party, the client, and the authenticator. The relying party is your application backend, while the client is the browser or native app. The authenticator is the biometrics chip or hardware key. This lifecycle consists of two primary phases: registration and assertion.

During registration, your application requests the creation of a new credential. The backend must generate a cryptographically secure random challenge to prevent replay attacks. The client-side application then invokes the WebAuthn API via JavaScript.

// TypeScript: Client-side Passkey Registration using WebAuthn API
interface PasskeyRegistrationOptions {
  challenge: string;      // Base64URL encoded random bytes from the backend
  rpName: string;         // Relying Party name (your company name)
  rpId: string;           // Relying Party domain (must match current domain origin)
  userId: string;         // Unique user identifier generated by the backend
  userName: string;       // User's login name (e.g., email address)
  userDisplayName: string;// User's readable display name
}

export async function registerPasskey(options: PasskeyRegistrationOptions): Promise<PublicKeyCredential | null> {
  try {
    // Convert base64url challenge and user ID string to ArrayBuffer objects
    const challengeBuffer = Uint8Array.from(atob(options.challenge), c => c.charCodeAt(0));
    const userIdBuffer = new TextEncoder().encode(options.userId);

    const publicKeyCredentialCreationOptions: PublicKeyCredentialCreationOptions = {
      challenge: challengeBuffer,
      rp: {
        name: options.rpName,
        id: options.rpId, // e.g., "portal.projectmakers.de"
      },
      user: {
        id: userIdBuffer,
        name: options.userName,
        displayName: options.userDisplayName,
      },
      pubKeyCredParams: [
        {
          type: "public-key",
          alg: -7, // ES256: ECDSA using P-256 curve and SHA-256 (standard for mobile/biometrics)
        },
        {
          type: "public-key",
          alg: -257, // RS256: RSASSA-PKCS1-v1_5 using SHA-256 (fallback for legacy systems)
        }
      ],
      authenticatorSelection: {
        authenticatorAttachment: "platform", // "platform" forces FaceID/TouchID/Windows Hello
        userVerification: "required",        // Demands PIN or biometric confirmation
        residentKey: "required",             // Required for passwordless (discoverable credentials)
      },
      timeout: 60000, // 60-second execution window
      attestation: "none" // Omit hardware attestation data for privacy and compliance
    };

    const credential = await navigator.credentials.create({
      publicKey: publicKeyCredentialCreationOptions
    }) as PublicKeyCredential;

    return credential;
  } catch (error) {
    console.error("Passkey registration failed in the browser:", error);
    throw error;
  }
}

In this code, rp.id must strictly match the current domain origin of the application. The pubKeyCredParams array specifies the cryptographic algorithms, where ES256 represents ECDSA using P-256 and SHA-256. The option userVerification: 'required' guarantees that the device prompts the user for biometrics or a PIN. This ensures two factors are validated in a single, seamless gesture.

When a user attempts to log in, the backend issues another unique challenge. The frontend calls navigator.credentials.get(), passing the challenge and the registered credential ID. The authenticator prompts the user for their biometric gesture, signs the challenge, and returns the signature to the frontend. The backend verifies this signature using the stored public key to authorize the session.

Integrating Passkeys with Microsoft Entra ID and Custom Apps

When your organization relies on Microsoft Entra ID as its primary Identity Provider (IdP), enabling passkeys requires synchronizing Entra ID policies with your custom application's authentication flow. Microsoft's update means Entra ID will actively prompt users to register and use passkeys when logging in. However, if your custom applications use outdated client libraries, these prompts can trigger errors or crash the authentication sequence.

To support the default passkey authentication, you must update the Microsoft Authentication Library (MSAL) in your application codebase. Legacy versions of MSAL.js utilizing implicit grant flows do not properly handle the modern authorization code flow with PKCE. Ensure your web applications are updated to MSAL.js 3.x to support modern passwordless sessions. You must also verify that your client application does not intercept or block browser redirects.

A common point of failure occurs in native iOS and Android mobile apps that wrap web interfaces. Many legacy hybrid apps built with older versions of Cordova, Ionic, or React Native use standard WebViews. These embedded web engines do not expose the native device's biometrics to the WebAuthn API. When Entra ID attempts to prompt the user for a passkey, the authentication flow halts with a generic error.

To resolve this, mobile developers must migrate their authentication flows to use system-level browsers. On iOS, you must implement ASWebAuthenticationSession or SFAuthenticationSession. On Android, implement Chrome Custom Tabs using the Android Credential Manager API. These native bridges ensure that when Entra ID requests a passkey assertion, the operating system's native biometric prompt is correctly initialized.

Architectural Planning: Sovereignty, Modeling, and Lock-In

Before writing a single line of authentication code, tech leads must plan the architecture carefully. Authentication systems are notoriously difficult to change once deployed to production. Designing secure, intuitive authentication workflows is a collaborative challenge. To align your developers, security officers, and business stakeholders, leveraging collaborative software modeling benefits is a vital first step.

By modeling the state transitions of user enrollment, device registration, and administrator recovery flows before coding, teams can identify edge cases. This prevents costly architectural rework late in the development cycle. Furthermore, integrating deeply with Entra ID's proprietary ecosystem raises long-term compliance and hosting questions. Microsoft's push for passkeys dramatically improves security, but it also deepens your reliance on US-hosted cloud infrastructure.

For European enterprises operating under strict data sovereignty requirements, this vendor lock-in is a growing concern. In our analysis of ditching the US cloud, we discussed the lessons learned from the Swiss Military's transition to open-source, locally hosted platforms like OpenDesk. If your long-term IT strategy includes moving toward sovereign infrastructure, you should design your custom application's authentication layer to be provider-agnostic. Implementing standard-compliant WebAuthn protocols ensures your code remains portable for potential future migrations.

Technical Challenges of Passkey Implementations in the Enterprise

While an entra id passkey integration offers unparalleled security, implementing it across an entire enterprise presents several technical hurdles. The first is cross-device synchronization friction. If a user registers a platform passkey on their corporate Windows laptop via Windows Hello, the private key is locked to that specific laptop's TPM chip. If they later attempt to log into your custom mobile application from a corporate iPhone, they will not have access to that key.

To mitigate this, you must configure your application's user portal to support multiple registered credentials per user account. Additionally, you should guide users to register both a platform-bound authenticator and a cross-device roaming authenticator. Examples include a hardware-based YubiKey or a cloud-synced credential manager like iCloud Keychain. This ensures seamless access across different corporate-managed devices.

Another challenge is secure recovery and enrollment without relying on SMS fallbacks. If a user loses their physical key, how do they log back in? If your system allows them to easily reset their passkey via an SMS code, the security of your entire authentication system is degraded to the security of SMS. The recovery flow becomes the weakest link, which attackers will exploit.

To solve this, you must implement Microsoft Entra ID's Temporary Access Pass (TAP) feature. A TAP is a time-limited, one-time-use passcode that administrators can generate for a user. The user logs in with the TAP to bypass the passkey requirement just long enough to register a new biometric passkey on their new device. This process keeps the enrollment flow secure without relying on weak fallback methods.

Finally, forcing a hard transition to passkeys overnight across thousands of employees is a recipe for operational chaos. Enforcing MFA updates without a progressive enrollment window typically spikes internal IT support tickets by over 300% within the first 48 hours. Modern application interfaces must support a progressive onboarding strategy to phase in passkeys and prepare support staff for handling TAP generation.

Implementing Entra ID Passkey Integration: Step-by-Step

Enabling passkeys in Entra ID and configuring custom apps involves a specific sequence of administrative and technical steps. The first step is enabling FIDO2 security keys in the Microsoft Entra admin center. Navigate to Protection, then Authentication methods, and select Policies. Enable the FIDO2 Security Key method for either all users or a pilot security group.

Under the configuration tab, set 'Allow self-service registration' to yes. For high-security environments, you can also enforce key restrictions. This allows you to restrict registrations to specific hardware manufacturers by entering their Authenticator Attestation GUIDs (AAGUIDs). For example, you can specify that only enterprise-issued YubiKeys are allowed.

Next, configure the Temporary Access Pass (TAP) policy to enable secure onboarding. Enable the policy in the Authentication methods menu and configure the minimum and maximum lifetime limits. Set one-time use to yes to ensure that TAPs expire immediately after their first execution. This prevents credential reuse during the setup process.

Finally, modernize your client-side code and configure progressive onboarding. Upgrade your frontends to use the latest MSAL.js version and replace embedded WebViews in mobile apps with custom tabs. Detect WebAuthn support programmatically using JavaScript, then prompt the user with a banner during their active session to enroll their biometrics.

Best Practices for Enterprise Passkey Deployments

To ensure your passkey implementation is secure, compliant, and user-friendly, apply these battle-tested development practices. These tips help developers avoid common integration pitfalls while maximizing security guarantees.

  1. Never Allow Unsecured Fallbacks: Do not let users downgrade their session to SMS/voice if they fail to authenticate with a passkey. Doing so renders the entire security posture useless, as hackers will target the weak link. Instead, enforce a strict recovery flow utilizing Temporary Access Passes (TAP) issued by IT administrators after identity verification.

  2. Implement Hybrid Device Registration: Encourage users to register at least two authenticators. This should include one platform-bound authenticator (Windows Hello or TouchID) for daily use, and one roaming key (like a USB-C/NFC YubiKey) or a synced passkey. This setup provides cross-device fallback and prevents lockouts.

  3. Use AAGUID Filtering for High-Security Environments: If you operate in regulated industries like finance or healthcare, use Authenticator Attestation GUID (AAGUID) filtering in Entra ID. This restricts registration of hardware keys to those with specific security certifications (e.g., FIPS 140-2 Level 3). It ensures only corporate-approved authenticators can access the tenant.

  4. Upgrade Electron and Hybrid App Containers: If your custom desktop or mobile apps run inside web wrappers, ensure Electron is upgraded to version 20+ and Cordova/Capacitor apps use native plugins. This bridges the WebAuthn API to the OS credential manager. Without this, native biometrics prompts will fail to launch.

When to Partner: Building vs. Outsourcing Your Auth Architecture

Building a custom authentication system that bridges legacy enterprise databases with modern passwordless standards is a complex, high-risk endeavor. A single vulnerability in your token verification logic can lead to severe breaches. Doing this in-house means hiring for skills you only need once, and maintaining the result for years. An experienced partner like ProjectMakers delivers this integration as a secure, fixed-price project.

We handle the entire transition, from auditing your legacy codebase and upgrading MSAL integrations to establishing secure fallback workflows. This allows your internal team to focus entirely on your core product. Whether you need to secure a complex React web dashboard or a multi-platform Unity serious game, ProjectMakers provides the deep technical expertise required to implement WebAuthn and Entra ID protocols without disrupting user workflows.

Next Steps: Moving Toward Passwordless Compliance

The deprecation of SMS and voice MFA in Microsoft Entra ID is a clear signal that legacy authentication is no longer acceptable. Start by auditing your current user base to identify which devices do not support WebAuthn and configure a progressive enrollment policy. Planning a software or AI project? Get in touch with ProjectMakers for a free initial consultation to plan your migration strategy.


Source: Microsoft macht Passkeys zum Standard in Entra ID