There are many ways to implement user authentication in a modern application (mobile, desktop, tablet, web, etc). I have previously explored Authentication, Federation, and SSO; that post introduces several key concepts that are assumed here. At the intersection of user experience, authentication, supportability, and general security is the question of how is the user authenticated? There are many ways of doing this; from an end-user perspective, there may not be a noticeable difference between the approaches. From an overall identity capability perspective, the approach matters. We aren’t just talking about the difference between using a username and password validated against LDAP versus using a client certificate, but also which architectural component is performing that step. Back in the day, just about every application had its own custom login workflow (series of screens to authenticate the user). As recently as a couple of years ago, I was working with IT organizations that still did things this way.
For several years now, I’ve been recommending clients use the hosted login workflows (UIs) that are available in their Identity Providers (or, at least, a customized workflow that is hosted on the identity provider) because this:
- Facilitates abstracting user credentials away from the applications.
- This centralizes the login experience across the organization.
- Provides a choke point for enforcing certain authentication characteristics like Multi Factor Authentication (MFA) or mandatory password change.
- Together with a common set of authentication libraries for the various platforms in play, can implement a reliable signout mechanism.
- Provides a mechanism that can facilitate a global signout (logout) capability.
- Allows for global changes to the login workflow with minimal hassle.
- Facilitates SSO via a common IdP session cookie and spec-defined identity protocols.
- The authentication service can appropriately implement.
The first one is especially important from a security standpoint. Some industry literature provides a more nuanced approach to this and says this is really only important if the IdP and application development teams belong to different organizations (or maybe different lines of business). Every identity solution I’ve designed/implemented over the past six years abstracted the user’s credentials away from the application by using a hosted login workflow — only the IdP saw the credentials. Designing your application authentication mechanism from the ground up to work in this manner is more secure than a situation where individual applications can see user credentials.
What are the downsides of doing this?
- App developers no longer have direct control over this aspect of the user experience. I’ve encountered a couple of developers who really disliked this.
- The use of the standards-based identity protocols that are common today tend to involve multiple HTTP Redirects (maybe six or more). This can create delays in the app on slow network connections that wouldn’t otherwise be there.
- For native mobile apps (or desktop apps), an external browser has to be launched in order to interact with the hosted UI. In some circles, this is viewed as an extreme negative.
- In recent versions of iOS, launching that external browser from the app requires the user to consent each time. This further erodes the user experience.
- To bring control back to the application native mobile app, typically requires registering a protocol or URL for the application with the device OS. This creates a new attack surface that must be addressed. See PKCE and here.
When Single Sign On first became important for the user experience, the most common way of implementing it was through server-integration with the User Store (LDAP, Active Directory, SQL database). Each individual organization was almost universally responsible for collecting user credentials. Then, those credentials would be validated against the needed User Store. The OpenID Connect, SAML2, WS-Federation, and other identity protocols imply that an IdP-hosted login workflow should be used, but none of these protocols specifically state how the login mechanism should work.
For example, the OIDC spec states:
126.96.36.199. Authorization Server Authenticates End-User
If the request is valid, the Authorization Server attempts to Authenticate the End-User or determines whether the End-User is Authenticated, depending upon the request parameter values used. The methods used by the Authorization Server to Authenticate the End-User (e.g. username and password, session cookies, etc.) are beyond the scope of this specification. An Authentication user interface MAY be displayed by the Authorization Server, depending upon the request parameter values used and the authentication methods used.
The OAuth2 (RFC6749) states:
3.1. Authorization Endpoint
The authorization endpoint is used to interact with the resource
owner and obtain an authorization grant. The authorization server
MUST first verify the identity of the resource owner. The way in
which the authorization server authenticates the resource owner
(e.g., username and password login, session cookies) is beyond the
scope of this specification.
The SAML 2.0 spec states:
The <AuthnRequest> and <Response> exchange supports a variety of usage scenarios and is therefore typically profiled for use in a specific context in which this optionality is constrained and specific kinds of input and output are required or prohibited. The following processing rules apply as invariant behavior across any profile of this protocol exchange. All other processing rules associated with the underlying request and response messages MUST also be observed.
The WS-Federation spec states (look at the last sentence):
In the Web approach, there is a common pattern used when communicating with an IP/STS. In the first step, the requestor accesses the resource; the requestor is then redirected to an IP/STS if no token or cookie is supplied on the request. The requestor may MAY be redirected to a local IP/STS operated by the resource provider. If it has not cached data indicating that the requestor has already been authenticated, a second redirection to the requestor's IP/STS will be performed. This redirection process MAY require prompting the user to determine the requestor’s home realm. The IP/STS in the requestor’s home realm generates a security token for use by the federated party. This token MAY be consumed directly by the resource, or it MAY be exchanged at the resource’s IP/STS for a token consumable by the resource. In some cases the requestor’s IP/STS has the requisite information cached to be able to issue a token, in other cases it must prompt the user. Note that the resource’s IP/STS can be omitted if the resource is willing to consume the requestor’s token directly.
The figure below illustrates an example flow where there is no resource IP/STS. As depicted, all communication occurs with the standard HTTP GET and POST methods, using redirects (steps 2à3 and 5à6) to automate the communication. Note that when returning non-URL content a POST is REQUIRED (e.g. in step 6) if a result reference is not used. In step 2 the resource MAY act as its own IP/STS so communication with an additional service isn't required. Note that step 3 depicts the resource redirecting directly to the requestor’s IP/STS. As previously discussed, this could redirect to an IP/STS for the resource (or any number of chained IP/STS services). It might also redirect to a home realm discovery service.
It should be noted that in step 4, the authentication protocol employed MAY be implementation-dependent.
So, we have four different identity protocol specifications and four different statements to the effect of “how the user is authenticated is beyond the scope of this spec”. This is useful for each of these specs because it means that each can be employed in a wide variety of use cases and authentication scenarios (username + password, MFA, OTP, secureId, client certificates, digital signatures, FIDO2 WebAuthN, session cookies, etc.).
So, by extension, none of these specs explicitly requires the IdP to use a hosted login workflow. In fact, the OAuth2 spec defines an Authorization Grant that supports using an application-hosted login workflow, but only with a username and password; though, use of this grant is generally discouraged today. So, we are left with the list of pros and cons where this post started.
If you insist on having the login workflow (authentication service) built into your application, then you must address how to securely integrate that workflow into your identity provider. This will likely involve implementing some type of custom interface/module on the IdP. Regardless of the details, it involves custom coding that amounts to a custom security solution. I wish you luck. I would strongly encourage your organization to do a professional penetration test and security audit of this application/system before it goes live in production, especially if it is facing the public internet.
For the reasons listed the beginning of this post, I always recommend using an IdP-hosted login workflow. That being said, even if you do this, but fail to follow best practices throughout the rest of your Identity and Access Management (IAM) infrastructure, little has been accomplished — that for another post. But, please do NOT store clear text user passwords in LDAP, AD, or a database.
Image: Ankor Wat / Ramiro Ramirez