Securing identity: Exploring application types and authentication flows

Adam Matthews

In part one of our series, we explored the essentials of identity and access management (IAM), laying the groundwork for understanding how robust IAM practices can enhance the security and usability of your applications. If you haven’t read it yet, we highly recommend starting there first to get a comprehensive overview of IAM fundamentals.

Building on the foundation laid out in part one, this blog post delves deeper into the world of application types and authentication flows. Our focus is on helping you navigate the complexities of securing applications through the proper implementation of authentication frameworks. Understanding these different types of authentication flows, how they work, and when to use them is essential for protecting user data and ensuring a seamless user experience.

We acknowledge that the landscape of digital security is constantly evolving. And the guidance outlined below, like most security guidance, is subject to change as the landscape evolves. We’ve done our best to provide the most up-to-date information at the time of writing, but staying informed is key to maintaining the security and integrity of your applications. Let’s continue our journey and explore the intricacies of authentication flows, examining best practices for different application types and how to implement them effectively. By the end of this blog post, you should have a clearer understanding of how to choose and implement the most appropriate authentication flow for your application.

Using MSAL for your applications

As we begin to look at app types and their recommended flows, it’s important to consider the simplicity and security that the Microsoft Authentication Library (MSAL) brings to your development process.

If you’re clear on the type of app you’re building and there’s an MSAL library available for your platform, then you can largely side-step having to choose a specific authentication protocol. Instead, start leveraging MSAL’s methods, knowing that the correct protocols have already been chosen for you. Our implementations come with the assurance of being security reviewed and tested.

This approach makes the development process more efficient and solidifies your application’s security framework, ensuring you’re building on a foundation of trusted, up-to-date practices. With that being said, let’s dive into the specifics of app types and their recommended authentication flow.

Understanding app types and recommended flows

When considering app types and their recommended authentication flows, it’s important to understand the concept of ‘clients’, as this will influence the choice of authentication flow. A client is a software entity, such as a web app, mobile app, or service that has a unique identifier assigned by an Identity Provider (IdP), such as Microsoft Entra ID. Clients can be categorized into two main types: public and confidential.

Public clients

  • Public clients cannot securely store credentials or ‘secrets’—pieces of information used to prove identity. Public clients are applications that can be downloaded and run on devices, such as mobile, desktop, or client-side browser apps. Basically, any time the source, binary, or executable can be accessed by untrusted parties, it’s a public client.

Confidential clients

  • Confidential clients, on the other hand, can securely store secrets. They are server-side applications, such as backend-driven web apps or web APIs that have secure, server-to-server communication without exposure to end-users. Making them less vulnerable compared to public clients.

Public client app types

Single-page applications (SPAs)

Single-page applications are client-side web applications that load a single page that runs in the browser. Content gets dynamically updated as the user interacts with the application, or at application load time. These modern web applications use JavaScript or frameworks like Angular, that eliminate the need for page reloads. MSAL.js and Blazor support single-page applications.

For SPAs, the Authorization Code Flow with Proof Key for Code Exchange (PKCE) is the recommended flow. In fact, we recommend that existing single-page applications be migrated from the implicit flow to the authorization code flow with PKCE. This improves the resiliency, security, and user experience of SPAs, particularly when a user is on a browser that blocks third-party cookies by default. The Authorization Code Flow with PKCE adds an extra layer of security, mitigating the risk of interception during the authorization process. It’s specifically designed to work well in public clients where client secrets cannot be stored securely.

Native applications

Desktop applications

Desktop applications run on personal computers and can handle a wide variety of processes, from document editing to running development environments. Because a desktop application runs on a user’s personal computer, or desktop, it is a public client, and unable to store secrets securely.

Mobile applications

Mobile applications are specially designed for mobile devices. Think of the wide variety of tasks you might perform on your phone on a day-to-day basis. Similar to desktop applications, mobile applications run on end user devices, such as mobile phones, tablets, or wearables, so they’re considered public clients that are unable to store secrets securely.

For desktop and mobile applications, the Authorization Code Flow with PKCE is the recommended flow. This approach accommodates a desktop environment’s security considerations, avoiding the need to store client secrets in the application. It also does not require mobile apps to store secrets, making it suitable for apps on devices that might be lost or compromised.

Input-constrained devices

Input-constrained devices are devices that either don’t have a browser or have limited input capabilities, such as TVs, IoT devices, or printers.

For input-constrained devices, the Device Code Flow is the recommended flow. It enables these types of devices to securely authenticate a user without requiring the user to input their credentials directly into the device.

Confidential client app types

Web applications

Web applications run code on a server that generates and sends HTML, CSS, and JavaScript to be rendered on a browser. Because the code runs on a server, they’re considered confidential clients that can store secrets securely. These applications handle requests and responses from multiple users and are used for websites and services that require user interaction and data processing.

For web applications, the Authorization Code Flow with PKCE is the recommended flow. This flow allows the application to securely authenticate the user and obtain tokens without exposing them to the client browser, thus ensuring the security of user data and access tokens. If your web app needs to access an API or service on behalf of a user or itself, please keep reading further to learn more about delegated and app-only service-to-service authentication.

If your scenario involves signing in a user and not calling any other downstream services, consider looking at the built-in capabilities of ASP.NET Core.

Web APIs

Web APIs act as intermediaries, providing services to other applications rather than directly to users. When both origin and destination for a request are services, this is referred to as a service-to-service (S2S) call. Web APIs play a crucial role in modern application development, enabling them to extend their capabilities by leveraging external functionality and data.

For web APIs that call other web APIs on behalf of a user, the On Behalf of Flow is the recommended flow. This flow allows the web API to request tokens to access other resources, ensuring actions are performed with the scope of the user’s permissions. For APIs that are accessed by daemons, services, or other non-interactive applications, see the next section.

Server-side daemon or service applications

Server-side daemon or service applications are known as server-side applications. They operate in the background and are used for server-to-server and other unattended, or headless, communication. There is no user at the keyboard to enter credentials or consent to resource access.

These applications execute operations on behalf of the application itself, rather than a user. And because server-side daemon or service applications run on a server, they are considered confidential clients that can securely manage secrets and are less exposed to direct threats.

Note: daemons can technically be either public or confidential clients, i.e. non-server-side daemons can be considered public clients.

For server-side daemon or service applications, the use of Managed Identities is highly recommended as they provide a secure and automated way to manage credentials for services hosted on Azure. A common challenge for developers is the management of secrets, credentials, certificates, and keys used to secure communication between services. Managed identities eliminate the need for developers to manage these credentials. They offer an alternative to client credentials (see below), delegating the complexity of server-to-server authentication to the infrastructure layer—which is the approach we recommend, where possible.

If Managed Identities don’t meet your specific requirements, the Client Credentials Flow is suitable for processes that don’t require user interaction. It allows an application to authenticate directly with the identity provider on behalf of itself—using its own credentials to access protected resources.

Authentication flows explained

As we begin to take a more detailed look at authentication flows, it’s worth revisiting the benefits of the Microsoft Authentication Library (MSAL) mentioned above. MSAL simplifies your work by automating the choice of secure, up-to-date protocols, allowing you to focus on your application’s core features. Its security-reviewed, tested implementations mean you’re building with reliability and trust right from the start.

Authorization Code Flow

Use case: Web applications, single-page applications, mobile applications, desktop applications

The Authorization Code Flow is a secure way for users to log into applications and get permission to access data and services.

When a user wishes to log in to an application, they are redirected to the authentication server to enter their credentials. After logging in, the authentication server issues an authorization code which is sent to the application. The application exchanges this code for an access token by making a request to the authentication server which includes credentials to prove its identity. The authentication server verifies the code and credentials and issues an access token which can then be used by the application to access resources on behalf of the user.

The Authorization Code Flow with PKCE is an enhanced version of the Authorization Code Flow, designed to add security for applications that run on devices like smartphones, tablets, and computers, where storing secrets securely is challenging.

On Behalf of Flow

Use case: Web APIs

The On Behalf of Flow is used when an application needs to access resources or perform actions, on behalf of a user, but through another service.

A user logs in to an application (App A) using their credentials. App A gets an access token from the authentication server, proving the user has logged in. When App A needs to access or perform an action in another application (App B) on behalf of the user, it sends a request to the authentication server. This request includes the original access token and a request for a new token to access App B. The authentication server verifies the token from App A and issues a new token to be used to access App B on behalf of the user.

Client Credentials Flow

Use case: Daemon or service applications

The Client Credentials Flow can be used where daemon or server-side applications need to access data and/or services without acting on behalf of a user.

The application sends a request to the authentication server which includes credentials to prove its identity. The authentication server verifies these credentials and issues an access token to the application. The application can then use this token to make requests to access resources or services. This process doesn’t involve a user so there are no redirects or authorization codes. The application proves its own identity and receives a token to use in its operations.

Managed identities

Use case: Services hosted on Azure

Managed Identities simplify how applications running on Azure services access other Azure resources securely. Instead of handling credentials like keys and certificates, Managed Identities provide an automatic way for your apps to authenticate and access Azure services. This means less risk and hassle with managing sensitive data, as the infrastructure takes care of the identity management behind the scenes.

Device Code Flow

Use case: Input-constrained devices (Headless devices)

The Device Code Flow is used where access is required to devices that don’t have a browser or have limited input capabilities.

When a user wishes to log in to a device, the device requests a device code from the authentication server. The authentication server responds with a device code, a user code, and verification URL, which is shared with the user via the device. The user navigates to the URL on a separate device that has a browser, like a smartphone, and enters the user code. The user is then brought to a login page where they input their credentials. Once the device gets confirmation from the authentication server that the user has logged in, it receives an access token from the authentication server, which is what grants access to the device.

Best practices for implementing authentication flows

  • Store secrets securely
  • Delegate to infrastructure
    • Where possible, it’s recommended to delegate security handling to infrastructure, for example, using Managed Identities for credential management. The benefits of delegating security handling to infrastructure include enhanced security, in that it eliminates the chances of mishandling a secret, simplified credential management, and reduced operational overhead—resources from managing identities are freed up, reducing time and the potential for human error.
  • Have a plan in place
    • Have a response plan in place for how to rotate or retire secrets if compromised.
  • Validate Redirect URIs
    • Only allow redirect URIs that you trust and have registered with the authentication server. This ensures that authorization codes and tokens are only sent to authenticated URIs, preventing redirection attacks.
  • Minimize token lifespan
    • Use tokens with short expiration times where appropriate. This limits the potential impact if an access token has been compromised. Implement token refresh mechanisms to renew access when needed.
  • Implement appropriate consent
    • Ensure that you implement an appropriate consent framework. Users should fully understand what data the application is accessing and what actions it will perform.
  • Implement a smooth UX
    • Aim for a login process that’s as frictionless as possible to streamline the user experience. A bad experience can deter users from logging in or completing the authentication process.
  • Provide clear error messages
    • If authentication fails, give end users clear, helpful error messages. This helps them solve the issue and reduces frustration.
  • Test and monitor and update
    • Regularly test your authentication flows for vulnerabilities. Monitor and log authentication events for unusual activity. Implementing anomaly detection can help identify and mitigate potential security threats. Keep libraries and dependencies up-to-date and monitor for CVEs/vulnerability reports.

Keep growing, building, and learning

Choosing and implementing the right authentication flow is a foundational aspect of your application’s security posture and user experience. The Microsoft identity platform offers comprehensive frameworks for managing these flows across a variety of scenarios, from SPAs, mobile and web apps, to desktop apps and background services. By taking the best practices outlined above into consideration, you can ensure that your applications are both secure and accessible to users.

In this blog post, we’ve explored different application types, breaking them down into logical groupings of public and confidential clients. We’ve looked at the different authentication flows recommended for different types of applications. We’ve also outlined several key best practices to keep in mind when implementing authentication flows in your application, designed to protect the end user and maintain the integrity of your application.

We encourage you to explore the documentation at all stages of your journey and to keep your knowledge up to date with the latest developments in the authentication landscape.

  • Explore more: Visit the Microsoft identity platform documentation for detailed guides and tutorials on implementing these authentication flows.
  • Engage with the community: Share your experiences with implementing authentication flows in your applications. The learnings from any challenges you may have faced can provide valuable insights to the community.
  • Stay informed: To learn more or test out features in the Microsoft Entra portfolio, visit our developer center. Sign up for email updates on the Identity blog for more insights and to keep up with the latest on all things Identity. And, follow us on YouTube for video overviews, tutorials, and deep dives.

0 comments

Leave a comment

Feedback usabilla icon